ACodec.cpp revision d02ac2c7286ca7190ddaf861095cd0b16e28da1e
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    static_cast<Surface*>(mNativeWindow.get())
4160            ->getIGraphicBufferProducer()->allowAllocation(true);
4161
4162    err = mNativeWindow->query(mNativeWindow.get(),
4163            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
4164    if (err != NO_ERROR) {
4165        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
4166                "failed: %s (%d)", strerror(-err), -err);
4167        goto error;
4168    }
4169
4170    numBufs = minUndequeuedBufs + 1;
4171    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
4172    if (err != NO_ERROR) {
4173        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
4174                strerror(-err), -err);
4175        goto error;
4176    }
4177
4178    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
4179    // buffer twice.  This should guarantee that the buffer has been displayed
4180    // on the screen and then been replaced, so an previous video frames are
4181    // guaranteed NOT to be currently displayed.
4182    for (int i = 0; i < numBufs + 1; i++) {
4183        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
4184        if (err != NO_ERROR) {
4185            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
4186                    strerror(-err), -err);
4187            goto error;
4188        }
4189
4190        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
4191
4192        // Fill the buffer with the a 1x1 checkerboard pattern ;)
4193        uint32_t* img = NULL;
4194        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
4195        if (err != NO_ERROR) {
4196            ALOGE("error pushing blank frames: lock failed: %s (%d)",
4197                    strerror(-err), -err);
4198            goto error;
4199        }
4200
4201        *img = 0;
4202
4203        err = buf->unlock();
4204        if (err != NO_ERROR) {
4205            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
4206                    strerror(-err), -err);
4207            goto error;
4208        }
4209
4210        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
4211                buf->getNativeBuffer(), -1);
4212        if (err != NO_ERROR) {
4213            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
4214                    strerror(-err), -err);
4215            goto error;
4216        }
4217
4218        anb = NULL;
4219    }
4220
4221error:
4222
4223    if (err != NO_ERROR) {
4224        // Clean up after an error.
4225        if (anb != NULL) {
4226            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
4227        }
4228
4229        native_window_api_disconnect(mNativeWindow.get(),
4230                NATIVE_WINDOW_API_CPU);
4231        native_window_api_connect(mNativeWindow.get(),
4232                NATIVE_WINDOW_API_MEDIA);
4233
4234        return err;
4235    } else {
4236        // Clean up after success.
4237        err = native_window_api_disconnect(mNativeWindow.get(),
4238                NATIVE_WINDOW_API_CPU);
4239        if (err != NO_ERROR) {
4240            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
4241                    strerror(-err), -err);
4242            return err;
4243        }
4244
4245        err = native_window_api_connect(mNativeWindow.get(),
4246                NATIVE_WINDOW_API_MEDIA);
4247        if (err != NO_ERROR) {
4248            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
4249                    strerror(-err), -err);
4250            return err;
4251        }
4252
4253        return NO_ERROR;
4254    }
4255}
4256
4257////////////////////////////////////////////////////////////////////////////////
4258
4259ACodec::PortDescription::PortDescription() {
4260}
4261
4262status_t ACodec::requestIDRFrame() {
4263    if (!mIsEncoder) {
4264        return ERROR_UNSUPPORTED;
4265    }
4266
4267    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4268    InitOMXParams(&params);
4269
4270    params.nPortIndex = kPortIndexOutput;
4271    params.IntraRefreshVOP = OMX_TRUE;
4272
4273    return mOMX->setConfig(
4274            mNode,
4275            OMX_IndexConfigVideoIntraVOPRefresh,
4276            &params,
4277            sizeof(params));
4278}
4279
4280void ACodec::PortDescription::addBuffer(
4281        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
4282    mBufferIDs.push_back(id);
4283    mBuffers.push_back(buffer);
4284}
4285
4286size_t ACodec::PortDescription::countBuffers() {
4287    return mBufferIDs.size();
4288}
4289
4290IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4291    return mBufferIDs.itemAt(index);
4292}
4293
4294sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4295    return mBuffers.itemAt(index);
4296}
4297
4298////////////////////////////////////////////////////////////////////////////////
4299
4300ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4301    : AState(parentState),
4302      mCodec(codec) {
4303}
4304
4305ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4306        OMX_U32 /* portIndex */) {
4307    return KEEP_BUFFERS;
4308}
4309
4310bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4311    switch (msg->what()) {
4312        case kWhatInputBufferFilled:
4313        {
4314            onInputBufferFilled(msg);
4315            break;
4316        }
4317
4318        case kWhatOutputBufferDrained:
4319        {
4320            onOutputBufferDrained(msg);
4321            break;
4322        }
4323
4324        case ACodec::kWhatOMXMessage:
4325        {
4326            return onOMXMessage(msg);
4327        }
4328
4329        case ACodec::kWhatSetSurface:
4330        {
4331            sp<AReplyToken> replyID;
4332            CHECK(msg->senderAwaitsResponse(&replyID));
4333
4334            sp<RefBase> obj;
4335            CHECK(msg->findObject("surface", &obj));
4336
4337            status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
4338
4339            sp<AMessage> response = new AMessage;
4340            response->setInt32("err", err);
4341            response->postReply(replyID);
4342            break;
4343        }
4344
4345        case ACodec::kWhatCreateInputSurface:
4346        case ACodec::kWhatUsePersistentInputSurface:
4347        case ACodec::kWhatSignalEndOfInputStream:
4348        {
4349            // This may result in an app illegal state exception.
4350            ALOGE("Message 0x%x was not handled", msg->what());
4351            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4352            return true;
4353        }
4354
4355        case ACodec::kWhatOMXDied:
4356        {
4357            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4358            ALOGE("OMX/mediaserver died, signalling error!");
4359            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4360            break;
4361        }
4362
4363        case ACodec::kWhatReleaseCodecInstance:
4364        {
4365            ALOGI("[%s] forcing the release of codec",
4366                    mCodec->mComponentName.c_str());
4367            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4368            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4369                       mCodec->mComponentName.c_str(), err);
4370            sp<AMessage> notify = mCodec->mNotify->dup();
4371            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4372            notify->post();
4373            break;
4374        }
4375
4376        default:
4377            return false;
4378    }
4379
4380    return true;
4381}
4382
4383bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4384    int32_t type;
4385    CHECK(msg->findInt32("type", &type));
4386
4387    // there is a possibility that this is an outstanding message for a
4388    // codec that we have already destroyed
4389    if (mCodec->mNode == 0) {
4390        ALOGI("ignoring message as already freed component: %s",
4391                msg->debugString().c_str());
4392        return true;
4393    }
4394
4395    IOMX::node_id nodeID;
4396    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4397    CHECK_EQ(nodeID, mCodec->mNode);
4398
4399    switch (type) {
4400        case omx_message::EVENT:
4401        {
4402            int32_t event, data1, data2;
4403            CHECK(msg->findInt32("event", &event));
4404            CHECK(msg->findInt32("data1", &data1));
4405            CHECK(msg->findInt32("data2", &data2));
4406
4407            if (event == OMX_EventCmdComplete
4408                    && data1 == OMX_CommandFlush
4409                    && data2 == (int32_t)OMX_ALL) {
4410                // Use of this notification is not consistent across
4411                // implementations. We'll drop this notification and rely
4412                // on flush-complete notifications on the individual port
4413                // indices instead.
4414
4415                return true;
4416            }
4417
4418            return onOMXEvent(
4419                    static_cast<OMX_EVENTTYPE>(event),
4420                    static_cast<OMX_U32>(data1),
4421                    static_cast<OMX_U32>(data2));
4422        }
4423
4424        case omx_message::EMPTY_BUFFER_DONE:
4425        {
4426            IOMX::buffer_id bufferID;
4427            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4428
4429            return onOMXEmptyBufferDone(bufferID);
4430        }
4431
4432        case omx_message::FILL_BUFFER_DONE:
4433        {
4434            IOMX::buffer_id bufferID;
4435            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4436
4437            int32_t rangeOffset, rangeLength, flags;
4438            int64_t timeUs;
4439
4440            CHECK(msg->findInt32("range_offset", &rangeOffset));
4441            CHECK(msg->findInt32("range_length", &rangeLength));
4442            CHECK(msg->findInt32("flags", &flags));
4443            CHECK(msg->findInt64("timestamp", &timeUs));
4444
4445            return onOMXFillBufferDone(
4446                    bufferID,
4447                    (size_t)rangeOffset, (size_t)rangeLength,
4448                    (OMX_U32)flags,
4449                    timeUs);
4450        }
4451
4452        default:
4453            TRESPASS();
4454            break;
4455    }
4456}
4457
4458bool ACodec::BaseState::onOMXEvent(
4459        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4460    if (event != OMX_EventError) {
4461        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
4462             mCodec->mComponentName.c_str(), event, data1, data2);
4463
4464        return false;
4465    }
4466
4467    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
4468
4469    // verify OMX component sends back an error we expect.
4470    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4471    if (!isOMXError(omxError)) {
4472        ALOGW("Invalid OMX error %#x", omxError);
4473        omxError = OMX_ErrorUndefined;
4474    }
4475    mCodec->signalError(omxError);
4476
4477    return true;
4478}
4479
4480bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4481    ALOGV("[%s] onOMXEmptyBufferDone %u",
4482         mCodec->mComponentName.c_str(), bufferID);
4483
4484    BufferInfo *info =
4485        mCodec->findBufferByID(kPortIndexInput, bufferID);
4486
4487    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4488    info->mStatus = BufferInfo::OWNED_BY_US;
4489
4490    // We're in "store-metadata-in-buffers" mode, the underlying
4491    // OMX component had access to data that's implicitly refcounted
4492    // by this "MediaBuffer" object. Now that the OMX component has
4493    // told us that it's done with the input buffer, we can decrement
4494    // the mediaBuffer's reference count.
4495    info->mData->setMediaBufferBase(NULL);
4496
4497    PortMode mode = getPortMode(kPortIndexInput);
4498
4499    switch (mode) {
4500        case KEEP_BUFFERS:
4501            break;
4502
4503        case RESUBMIT_BUFFERS:
4504            postFillThisBuffer(info);
4505            break;
4506
4507        default:
4508        {
4509            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4510            TRESPASS();  // Not currently used
4511            break;
4512        }
4513    }
4514
4515    return true;
4516}
4517
4518void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4519    if (mCodec->mPortEOS[kPortIndexInput]) {
4520        return;
4521    }
4522
4523    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4524
4525    sp<AMessage> notify = mCodec->mNotify->dup();
4526    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4527    notify->setInt32("buffer-id", info->mBufferID);
4528
4529    info->mData->meta()->clear();
4530    notify->setBuffer("buffer", info->mData);
4531
4532    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
4533    reply->setInt32("buffer-id", info->mBufferID);
4534
4535    notify->setMessage("reply", reply);
4536
4537    notify->post();
4538
4539    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4540}
4541
4542void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4543    IOMX::buffer_id bufferID;
4544    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4545    sp<ABuffer> buffer;
4546    int32_t err = OK;
4547    bool eos = false;
4548    PortMode mode = getPortMode(kPortIndexInput);
4549
4550    if (!msg->findBuffer("buffer", &buffer)) {
4551        /* these are unfilled buffers returned by client */
4552        CHECK(msg->findInt32("err", &err));
4553
4554        if (err == OK) {
4555            /* buffers with no errors are returned on MediaCodec.flush */
4556            mode = KEEP_BUFFERS;
4557        } else {
4558            ALOGV("[%s] saw error %d instead of an input buffer",
4559                 mCodec->mComponentName.c_str(), err);
4560            eos = true;
4561        }
4562
4563        buffer.clear();
4564    }
4565
4566    int32_t tmp;
4567    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4568        eos = true;
4569        err = ERROR_END_OF_STREAM;
4570    }
4571
4572    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4573    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
4574
4575    info->mStatus = BufferInfo::OWNED_BY_US;
4576
4577    switch (mode) {
4578        case KEEP_BUFFERS:
4579        {
4580            if (eos) {
4581                if (!mCodec->mPortEOS[kPortIndexInput]) {
4582                    mCodec->mPortEOS[kPortIndexInput] = true;
4583                    mCodec->mInputEOSResult = err;
4584                }
4585            }
4586            break;
4587        }
4588
4589        case RESUBMIT_BUFFERS:
4590        {
4591            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4592                int64_t timeUs;
4593                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4594
4595                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4596
4597                int32_t isCSD;
4598                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4599                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4600                }
4601
4602                if (eos) {
4603                    flags |= OMX_BUFFERFLAG_EOS;
4604                }
4605
4606                if (buffer != info->mData) {
4607                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
4608                         mCodec->mComponentName.c_str(),
4609                         bufferID,
4610                         buffer.get(), info->mData.get());
4611
4612                    CHECK_LE(buffer->size(), info->mData->capacity());
4613                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4614                }
4615
4616                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4617                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
4618                         mCodec->mComponentName.c_str(), bufferID);
4619                } else if (flags & OMX_BUFFERFLAG_EOS) {
4620                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
4621                         mCodec->mComponentName.c_str(), bufferID);
4622                } else {
4623#if TRACK_BUFFER_TIMING
4624                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
4625                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4626#else
4627                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
4628                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4629#endif
4630                }
4631
4632#if TRACK_BUFFER_TIMING
4633                ACodec::BufferStats stats;
4634                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4635                stats.mFillBufferDoneTimeUs = -1ll;
4636                mCodec->mBufferStats.add(timeUs, stats);
4637#endif
4638
4639                if (mCodec->mStoreMetaDataInOutputBuffers) {
4640                    // try to submit an output buffer for each input buffer
4641                    PortMode outputMode = getPortMode(kPortIndexOutput);
4642
4643                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4644                            mCodec->mMetaDataBuffersToSubmit,
4645                            (outputMode == FREE_BUFFERS ? "FREE" :
4646                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4647                    if (outputMode == RESUBMIT_BUFFERS) {
4648                        mCodec->submitOutputMetaDataBuffer();
4649                    }
4650                }
4651
4652                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4653                            mCodec->mNode,
4654                            bufferID,
4655                            0,
4656                            buffer->size(),
4657                            flags,
4658                            timeUs),
4659                         (status_t)OK);
4660
4661                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4662
4663                if (!eos) {
4664                    getMoreInputDataIfPossible();
4665                } else {
4666                    ALOGV("[%s] Signalled EOS on the input port",
4667                         mCodec->mComponentName.c_str());
4668
4669                    mCodec->mPortEOS[kPortIndexInput] = true;
4670                    mCodec->mInputEOSResult = err;
4671                }
4672            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4673                if (err != ERROR_END_OF_STREAM) {
4674                    ALOGV("[%s] Signalling EOS on the input port "
4675                         "due to error %d",
4676                         mCodec->mComponentName.c_str(), err);
4677                } else {
4678                    ALOGV("[%s] Signalling EOS on the input port",
4679                         mCodec->mComponentName.c_str());
4680                }
4681
4682                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
4683                     mCodec->mComponentName.c_str(), bufferID);
4684
4685                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4686                            mCodec->mNode,
4687                            bufferID,
4688                            0,
4689                            0,
4690                            OMX_BUFFERFLAG_EOS,
4691                            0),
4692                         (status_t)OK);
4693
4694                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4695
4696                mCodec->mPortEOS[kPortIndexInput] = true;
4697                mCodec->mInputEOSResult = err;
4698            }
4699            break;
4700        }
4701
4702        default:
4703            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4704            break;
4705    }
4706}
4707
4708void ACodec::BaseState::getMoreInputDataIfPossible() {
4709    if (mCodec->mPortEOS[kPortIndexInput]) {
4710        return;
4711    }
4712
4713    BufferInfo *eligible = NULL;
4714
4715    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4716        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4717
4718#if 0
4719        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4720            // There's already a "read" pending.
4721            return;
4722        }
4723#endif
4724
4725        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4726            eligible = info;
4727        }
4728    }
4729
4730    if (eligible == NULL) {
4731        return;
4732    }
4733
4734    postFillThisBuffer(eligible);
4735}
4736
4737bool ACodec::BaseState::onOMXFillBufferDone(
4738        IOMX::buffer_id bufferID,
4739        size_t rangeOffset, size_t rangeLength,
4740        OMX_U32 flags,
4741        int64_t timeUs) {
4742    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4743         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4744
4745    ssize_t index;
4746
4747#if TRACK_BUFFER_TIMING
4748    index = mCodec->mBufferStats.indexOfKey(timeUs);
4749    if (index >= 0) {
4750        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4751        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4752
4753        ALOGI("frame PTS %lld: %lld",
4754                timeUs,
4755                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4756
4757        mCodec->mBufferStats.removeItemsAt(index);
4758        stats = NULL;
4759    }
4760#endif
4761
4762    BufferInfo *info =
4763        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4764
4765    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4766
4767    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4768    info->mStatus = BufferInfo::OWNED_BY_US;
4769
4770    PortMode mode = getPortMode(kPortIndexOutput);
4771
4772    switch (mode) {
4773        case KEEP_BUFFERS:
4774            break;
4775
4776        case RESUBMIT_BUFFERS:
4777        {
4778            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4779                    || mCodec->mPortEOS[kPortIndexOutput])) {
4780                ALOGV("[%s] calling fillBuffer %u",
4781                     mCodec->mComponentName.c_str(), info->mBufferID);
4782
4783                CHECK_EQ(mCodec->mOMX->fillBuffer(
4784                            mCodec->mNode, info->mBufferID),
4785                         (status_t)OK);
4786
4787                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4788                break;
4789            }
4790
4791            sp<AMessage> reply =
4792                new AMessage(kWhatOutputBufferDrained, mCodec);
4793
4794            if (!mCodec->mSentFormat && rangeLength > 0) {
4795                mCodec->sendFormatChange(reply);
4796            }
4797
4798            if (mCodec->mUseMetadataOnEncoderOutput) {
4799                native_handle_t* handle =
4800                        *(native_handle_t**)(info->mData->data() + 4);
4801                info->mData->meta()->setPointer("handle", handle);
4802                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4803                info->mData->meta()->setInt32("rangeLength", rangeLength);
4804            } else {
4805                info->mData->setRange(rangeOffset, rangeLength);
4806            }
4807#if 0
4808            if (mCodec->mNativeWindow == NULL) {
4809                if (IsIDR(info->mData)) {
4810                    ALOGI("IDR frame");
4811                }
4812            }
4813#endif
4814
4815            if (mCodec->mSkipCutBuffer != NULL) {
4816                mCodec->mSkipCutBuffer->submit(info->mData);
4817            }
4818            info->mData->meta()->setInt64("timeUs", timeUs);
4819
4820            sp<AMessage> notify = mCodec->mNotify->dup();
4821            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4822            notify->setInt32("buffer-id", info->mBufferID);
4823            notify->setBuffer("buffer", info->mData);
4824            notify->setInt32("flags", flags);
4825
4826            reply->setInt32("buffer-id", info->mBufferID);
4827
4828            notify->setMessage("reply", reply);
4829
4830            notify->post();
4831
4832            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4833
4834            if (flags & OMX_BUFFERFLAG_EOS) {
4835                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4836
4837                sp<AMessage> notify = mCodec->mNotify->dup();
4838                notify->setInt32("what", CodecBase::kWhatEOS);
4839                notify->setInt32("err", mCodec->mInputEOSResult);
4840                notify->post();
4841
4842                mCodec->mPortEOS[kPortIndexOutput] = true;
4843            }
4844            break;
4845        }
4846
4847        default:
4848        {
4849            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4850
4851            CHECK_EQ((status_t)OK,
4852                     mCodec->freeBuffer(kPortIndexOutput, index));
4853            break;
4854        }
4855    }
4856
4857    return true;
4858}
4859
4860void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4861    IOMX::buffer_id bufferID;
4862    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4863    ssize_t index;
4864    BufferInfo *info =
4865        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4866    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4867
4868    android_native_rect_t crop;
4869    if (msg->findRect("crop",
4870            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4871        CHECK_EQ(0, native_window_set_crop(
4872                mCodec->mNativeWindow.get(), &crop));
4873    }
4874
4875    int32_t render;
4876    if (mCodec->mNativeWindow != NULL
4877            && msg->findInt32("render", &render) && render != 0
4878            && info->mData != NULL && info->mData->size() != 0) {
4879        ATRACE_NAME("render");
4880        // The client wants this buffer to be rendered.
4881
4882        int64_t timestampNs = 0;
4883        if (!msg->findInt64("timestampNs", &timestampNs)) {
4884            // TODO: it seems like we should use the timestamp
4885            // in the (media)buffer as it potentially came from
4886            // an input surface, but we did not propagate it prior to
4887            // API 20.  Perhaps check for target SDK version.
4888#if 0
4889            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4890                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4891                timestampNs *= 1000;
4892            }
4893#endif
4894        }
4895
4896        status_t err;
4897        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4898        if (err != OK) {
4899            ALOGW("failed to set buffer timestamp: %d", err);
4900        }
4901
4902        if ((err = mCodec->mNativeWindow->queueBuffer(
4903                    mCodec->mNativeWindow.get(),
4904                    info->mGraphicBuffer.get(), -1)) == OK) {
4905            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4906        } else {
4907            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4908            info->mStatus = BufferInfo::OWNED_BY_US;
4909        }
4910    } else {
4911        if (mCodec->mNativeWindow != NULL &&
4912            (info->mData == NULL || info->mData->size() != 0)) {
4913            ATRACE_NAME("frame-drop");
4914        }
4915        info->mStatus = BufferInfo::OWNED_BY_US;
4916    }
4917
4918    PortMode mode = getPortMode(kPortIndexOutput);
4919
4920    switch (mode) {
4921        case KEEP_BUFFERS:
4922        {
4923            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4924
4925            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4926                // We cannot resubmit the buffer we just rendered, dequeue
4927                // the spare instead.
4928
4929                info = mCodec->dequeueBufferFromNativeWindow();
4930            }
4931            break;
4932        }
4933
4934        case RESUBMIT_BUFFERS:
4935        {
4936            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4937                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4938                    // We cannot resubmit the buffer we just rendered, dequeue
4939                    // the spare instead.
4940
4941                    info = mCodec->dequeueBufferFromNativeWindow();
4942                }
4943
4944                if (info != NULL) {
4945                    ALOGV("[%s] calling fillBuffer %u",
4946                         mCodec->mComponentName.c_str(), info->mBufferID);
4947
4948                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4949                             (status_t)OK);
4950
4951                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4952                }
4953            }
4954            break;
4955        }
4956
4957        default:
4958        {
4959            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4960
4961            CHECK_EQ((status_t)OK,
4962                     mCodec->freeBuffer(kPortIndexOutput, index));
4963            break;
4964        }
4965    }
4966}
4967
4968////////////////////////////////////////////////////////////////////////////////
4969
4970ACodec::UninitializedState::UninitializedState(ACodec *codec)
4971    : BaseState(codec) {
4972}
4973
4974void ACodec::UninitializedState::stateEntered() {
4975    ALOGV("Now uninitialized");
4976
4977    if (mDeathNotifier != NULL) {
4978        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
4979        mDeathNotifier.clear();
4980    }
4981
4982    mCodec->mNativeWindow.clear();
4983    mCodec->mNode = 0;
4984    mCodec->mOMX.clear();
4985    mCodec->mQuirks = 0;
4986    mCodec->mFlags = 0;
4987    mCodec->mUseMetadataOnEncoderOutput = 0;
4988    mCodec->mComponentName.clear();
4989}
4990
4991bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4992    bool handled = false;
4993
4994    switch (msg->what()) {
4995        case ACodec::kWhatSetup:
4996        {
4997            onSetup(msg);
4998
4999            handled = true;
5000            break;
5001        }
5002
5003        case ACodec::kWhatAllocateComponent:
5004        {
5005            onAllocateComponent(msg);
5006            handled = true;
5007            break;
5008        }
5009
5010        case ACodec::kWhatShutdown:
5011        {
5012            int32_t keepComponentAllocated;
5013            CHECK(msg->findInt32(
5014                        "keepComponentAllocated", &keepComponentAllocated));
5015            ALOGW_IF(keepComponentAllocated,
5016                     "cannot keep component allocated on shutdown in Uninitialized state");
5017
5018            sp<AMessage> notify = mCodec->mNotify->dup();
5019            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5020            notify->post();
5021
5022            handled = true;
5023            break;
5024        }
5025
5026        case ACodec::kWhatFlush:
5027        {
5028            sp<AMessage> notify = mCodec->mNotify->dup();
5029            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5030            notify->post();
5031
5032            handled = true;
5033            break;
5034        }
5035
5036        case ACodec::kWhatReleaseCodecInstance:
5037        {
5038            // nothing to do, as we have already signaled shutdown
5039            handled = true;
5040            break;
5041        }
5042
5043        default:
5044            return BaseState::onMessageReceived(msg);
5045    }
5046
5047    return handled;
5048}
5049
5050void ACodec::UninitializedState::onSetup(
5051        const sp<AMessage> &msg) {
5052    if (onAllocateComponent(msg)
5053            && mCodec->mLoadedState->onConfigureComponent(msg)) {
5054        mCodec->mLoadedState->onStart();
5055    }
5056}
5057
5058bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
5059    ALOGV("onAllocateComponent");
5060
5061    CHECK(mCodec->mNode == 0);
5062
5063    OMXClient client;
5064    if (client.connect() != OK) {
5065        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
5066        return false;
5067    }
5068
5069    sp<IOMX> omx = client.interface();
5070
5071    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
5072
5073    mDeathNotifier = new DeathNotifier(notify);
5074    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
5075        // This was a local binder, if it dies so do we, we won't care
5076        // about any notifications in the afterlife.
5077        mDeathNotifier.clear();
5078    }
5079
5080    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
5081
5082    AString mime;
5083
5084    AString componentName;
5085    uint32_t quirks = 0;
5086    int32_t encoder = false;
5087    if (msg->findString("componentName", &componentName)) {
5088        ssize_t index = matchingCodecs.add();
5089        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
5090        entry->mName = String8(componentName.c_str());
5091
5092        if (!OMXCodec::findCodecQuirks(
5093                    componentName.c_str(), &entry->mQuirks)) {
5094            entry->mQuirks = 0;
5095        }
5096    } else {
5097        CHECK(msg->findString("mime", &mime));
5098
5099        if (!msg->findInt32("encoder", &encoder)) {
5100            encoder = false;
5101        }
5102
5103        OMXCodec::findMatchingCodecs(
5104                mime.c_str(),
5105                encoder, // createEncoder
5106                NULL,  // matchComponentName
5107                0,     // flags
5108                &matchingCodecs);
5109    }
5110
5111    sp<CodecObserver> observer = new CodecObserver;
5112    IOMX::node_id node = 0;
5113
5114    status_t err = OMX_ErrorComponentNotFound;
5115    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
5116            ++matchIndex) {
5117        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
5118        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
5119
5120        pid_t tid = gettid();
5121        int prevPriority = androidGetThreadPriority(tid);
5122        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
5123        err = omx->allocateNode(componentName.c_str(), observer, &node);
5124        androidSetThreadPriority(tid, prevPriority);
5125
5126        if (err == OK) {
5127            break;
5128        } else {
5129            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
5130        }
5131
5132        node = 0;
5133    }
5134
5135    if (node == 0) {
5136        if (!mime.empty()) {
5137            ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
5138                    encoder ? "en" : "de", mime.c_str(), err);
5139        } else {
5140            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
5141        }
5142
5143        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
5144        return false;
5145    }
5146
5147    notify = new AMessage(kWhatOMXMessage, mCodec);
5148    observer->setNotificationMessage(notify);
5149
5150    mCodec->mComponentName = componentName;
5151    mCodec->mFlags = 0;
5152
5153    if (componentName.endsWith(".secure")) {
5154        mCodec->mFlags |= kFlagIsSecure;
5155        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
5156        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
5157    }
5158
5159    mCodec->mQuirks = quirks;
5160    mCodec->mOMX = omx;
5161    mCodec->mNode = node;
5162
5163    {
5164        sp<AMessage> notify = mCodec->mNotify->dup();
5165        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
5166        notify->setString("componentName", mCodec->mComponentName.c_str());
5167        notify->post();
5168    }
5169
5170    mCodec->changeState(mCodec->mLoadedState);
5171
5172    return true;
5173}
5174
5175////////////////////////////////////////////////////////////////////////////////
5176
5177ACodec::LoadedState::LoadedState(ACodec *codec)
5178    : BaseState(codec) {
5179}
5180
5181void ACodec::LoadedState::stateEntered() {
5182    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
5183
5184    mCodec->mPortEOS[kPortIndexInput] =
5185        mCodec->mPortEOS[kPortIndexOutput] = false;
5186
5187    mCodec->mInputEOSResult = OK;
5188
5189    mCodec->mDequeueCounter = 0;
5190    mCodec->mMetaDataBuffersToSubmit = 0;
5191    mCodec->mRepeatFrameDelayUs = -1ll;
5192    mCodec->mInputFormat.clear();
5193    mCodec->mOutputFormat.clear();
5194    mCodec->mBaseOutputFormat.clear();
5195
5196    if (mCodec->mShutdownInProgress) {
5197        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
5198
5199        mCodec->mShutdownInProgress = false;
5200        mCodec->mKeepComponentAllocated = false;
5201
5202        onShutdown(keepComponentAllocated);
5203    }
5204    mCodec->mExplicitShutdown = false;
5205
5206    mCodec->processDeferredMessages();
5207}
5208
5209void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
5210    if (!keepComponentAllocated) {
5211        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
5212
5213        mCodec->changeState(mCodec->mUninitializedState);
5214    }
5215
5216    if (mCodec->mExplicitShutdown) {
5217        sp<AMessage> notify = mCodec->mNotify->dup();
5218        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5219        notify->post();
5220        mCodec->mExplicitShutdown = false;
5221    }
5222}
5223
5224bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5225    bool handled = false;
5226
5227    switch (msg->what()) {
5228        case ACodec::kWhatConfigureComponent:
5229        {
5230            onConfigureComponent(msg);
5231            handled = true;
5232            break;
5233        }
5234
5235        case ACodec::kWhatCreateInputSurface:
5236        {
5237            onCreateInputSurface(msg);
5238            handled = true;
5239            break;
5240        }
5241
5242        case ACodec::kWhatUsePersistentInputSurface:
5243        {
5244            onUsePersistentInputSurface(msg);
5245            handled = true;
5246            break;
5247        }
5248
5249        case ACodec::kWhatStart:
5250        {
5251            onStart();
5252            handled = true;
5253            break;
5254        }
5255
5256        case ACodec::kWhatShutdown:
5257        {
5258            int32_t keepComponentAllocated;
5259            CHECK(msg->findInt32(
5260                        "keepComponentAllocated", &keepComponentAllocated));
5261
5262            mCodec->mExplicitShutdown = true;
5263            onShutdown(keepComponentAllocated);
5264
5265            handled = true;
5266            break;
5267        }
5268
5269        case ACodec::kWhatFlush:
5270        {
5271            sp<AMessage> notify = mCodec->mNotify->dup();
5272            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5273            notify->post();
5274
5275            handled = true;
5276            break;
5277        }
5278
5279        default:
5280            return BaseState::onMessageReceived(msg);
5281    }
5282
5283    return handled;
5284}
5285
5286bool ACodec::LoadedState::onConfigureComponent(
5287        const sp<AMessage> &msg) {
5288    ALOGV("onConfigureComponent");
5289
5290    CHECK(mCodec->mNode != 0);
5291
5292    AString mime;
5293    CHECK(msg->findString("mime", &mime));
5294
5295    status_t err = mCodec->configureCodec(mime.c_str(), msg);
5296
5297    if (err != OK) {
5298        ALOGE("[%s] configureCodec returning error %d",
5299              mCodec->mComponentName.c_str(), err);
5300
5301        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5302        return false;
5303    }
5304
5305    {
5306        sp<AMessage> notify = mCodec->mNotify->dup();
5307        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
5308        notify->setMessage("input-format", mCodec->mInputFormat);
5309        notify->setMessage("output-format", mCodec->mOutputFormat);
5310        notify->post();
5311    }
5312
5313    return true;
5314}
5315
5316status_t ACodec::LoadedState::setupInputSurface() {
5317    status_t err = OK;
5318
5319    if (mCodec->mRepeatFrameDelayUs > 0ll) {
5320        err = mCodec->mOMX->setInternalOption(
5321                mCodec->mNode,
5322                kPortIndexInput,
5323                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
5324                &mCodec->mRepeatFrameDelayUs,
5325                sizeof(mCodec->mRepeatFrameDelayUs));
5326
5327        if (err != OK) {
5328            ALOGE("[%s] Unable to configure option to repeat previous "
5329                  "frames (err %d)",
5330                  mCodec->mComponentName.c_str(),
5331                  err);
5332            return err;
5333        }
5334    }
5335
5336    if (mCodec->mMaxPtsGapUs > 0ll) {
5337        err = mCodec->mOMX->setInternalOption(
5338                mCodec->mNode,
5339                kPortIndexInput,
5340                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
5341                &mCodec->mMaxPtsGapUs,
5342                sizeof(mCodec->mMaxPtsGapUs));
5343
5344        if (err != OK) {
5345            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
5346                    mCodec->mComponentName.c_str(),
5347                    err);
5348            return err;
5349        }
5350    }
5351
5352    if (mCodec->mMaxFps > 0) {
5353        err = mCodec->mOMX->setInternalOption(
5354                mCodec->mNode,
5355                kPortIndexInput,
5356                IOMX::INTERNAL_OPTION_MAX_FPS,
5357                &mCodec->mMaxFps,
5358                sizeof(mCodec->mMaxFps));
5359
5360        if (err != OK) {
5361            ALOGE("[%s] Unable to configure max fps (err %d)",
5362                    mCodec->mComponentName.c_str(),
5363                    err);
5364            return err;
5365        }
5366    }
5367
5368    if (mCodec->mTimePerCaptureUs > 0ll
5369            && mCodec->mTimePerFrameUs > 0ll) {
5370        int64_t timeLapse[2];
5371        timeLapse[0] = mCodec->mTimePerFrameUs;
5372        timeLapse[1] = mCodec->mTimePerCaptureUs;
5373        err = mCodec->mOMX->setInternalOption(
5374                mCodec->mNode,
5375                kPortIndexInput,
5376                IOMX::INTERNAL_OPTION_TIME_LAPSE,
5377                &timeLapse[0],
5378                sizeof(timeLapse));
5379
5380        if (err != OK) {
5381            ALOGE("[%s] Unable to configure time lapse (err %d)",
5382                    mCodec->mComponentName.c_str(),
5383                    err);
5384            return err;
5385        }
5386    }
5387
5388    if (mCodec->mCreateInputBuffersSuspended) {
5389        bool suspend = true;
5390        err = mCodec->mOMX->setInternalOption(
5391                mCodec->mNode,
5392                kPortIndexInput,
5393                IOMX::INTERNAL_OPTION_SUSPEND,
5394                &suspend,
5395                sizeof(suspend));
5396
5397        if (err != OK) {
5398            ALOGE("[%s] Unable to configure option to suspend (err %d)",
5399                  mCodec->mComponentName.c_str(),
5400                  err);
5401            return err;
5402        }
5403    }
5404
5405    return OK;
5406}
5407
5408void ACodec::LoadedState::onCreateInputSurface(
5409        const sp<AMessage> & /* msg */) {
5410    ALOGV("onCreateInputSurface");
5411
5412    sp<AMessage> notify = mCodec->mNotify->dup();
5413    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
5414
5415    sp<IGraphicBufferProducer> bufferProducer;
5416    status_t err = mCodec->mOMX->createInputSurface(
5417            mCodec->mNode, kPortIndexInput, &bufferProducer);
5418
5419    if (err == OK) {
5420        err = setupInputSurface();
5421    }
5422
5423    if (err == OK) {
5424        notify->setObject("input-surface",
5425                new BufferProducerWrapper(bufferProducer));
5426    } else {
5427        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5428        // the error through because it's in the "configured" state.  We
5429        // send a kWhatInputSurfaceCreated with an error value instead.
5430        ALOGE("[%s] onCreateInputSurface returning error %d",
5431                mCodec->mComponentName.c_str(), err);
5432        notify->setInt32("err", err);
5433    }
5434    notify->post();
5435}
5436
5437void ACodec::LoadedState::onUsePersistentInputSurface(
5438        const sp<AMessage> &msg) {
5439    ALOGV("onUsePersistentInputSurface");
5440
5441    sp<AMessage> notify = mCodec->mNotify->dup();
5442    notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
5443
5444    sp<RefBase> obj;
5445    CHECK(msg->findObject("input-surface", &obj));
5446    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
5447
5448    status_t err = mCodec->mOMX->usePersistentInputSurface(
5449            mCodec->mNode, kPortIndexInput, surface->getBufferConsumer());
5450
5451    if (err == OK) {
5452        err = setupInputSurface();
5453    }
5454
5455    if (err != OK) {
5456        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5457        // the error through because it's in the "configured" state.  We
5458        // send a kWhatInputSurfaceAccepted with an error value instead.
5459        ALOGE("[%s] onUsePersistentInputSurface returning error %d",
5460                mCodec->mComponentName.c_str(), err);
5461        notify->setInt32("err", err);
5462    }
5463    notify->post();
5464}
5465
5466void ACodec::LoadedState::onStart() {
5467    ALOGV("onStart");
5468
5469    CHECK_EQ(mCodec->mOMX->sendCommand(
5470                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5471             (status_t)OK);
5472
5473    mCodec->changeState(mCodec->mLoadedToIdleState);
5474}
5475
5476////////////////////////////////////////////////////////////////////////////////
5477
5478ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5479    : BaseState(codec) {
5480}
5481
5482void ACodec::LoadedToIdleState::stateEntered() {
5483    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5484
5485    status_t err;
5486    if ((err = allocateBuffers()) != OK) {
5487        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5488             "(error 0x%08x)",
5489             err);
5490
5491        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5492
5493        mCodec->changeState(mCodec->mLoadedState);
5494    }
5495}
5496
5497status_t ACodec::LoadedToIdleState::allocateBuffers() {
5498    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5499
5500    if (err != OK) {
5501        return err;
5502    }
5503
5504    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5505}
5506
5507bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5508    switch (msg->what()) {
5509        case kWhatSetParameters:
5510        case kWhatShutdown:
5511        {
5512            mCodec->deferMessage(msg);
5513            return true;
5514        }
5515
5516        case kWhatSignalEndOfInputStream:
5517        {
5518            mCodec->onSignalEndOfInputStream();
5519            return true;
5520        }
5521
5522        case kWhatResume:
5523        {
5524            // We'll be active soon enough.
5525            return true;
5526        }
5527
5528        case kWhatFlush:
5529        {
5530            // We haven't even started yet, so we're flushed alright...
5531            sp<AMessage> notify = mCodec->mNotify->dup();
5532            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5533            notify->post();
5534            return true;
5535        }
5536
5537        default:
5538            return BaseState::onMessageReceived(msg);
5539    }
5540}
5541
5542bool ACodec::LoadedToIdleState::onOMXEvent(
5543        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5544    switch (event) {
5545        case OMX_EventCmdComplete:
5546        {
5547            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5548            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5549
5550            CHECK_EQ(mCodec->mOMX->sendCommand(
5551                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
5552                     (status_t)OK);
5553
5554            mCodec->changeState(mCodec->mIdleToExecutingState);
5555
5556            return true;
5557        }
5558
5559        default:
5560            return BaseState::onOMXEvent(event, data1, data2);
5561    }
5562}
5563
5564////////////////////////////////////////////////////////////////////////////////
5565
5566ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5567    : BaseState(codec) {
5568}
5569
5570void ACodec::IdleToExecutingState::stateEntered() {
5571    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5572}
5573
5574bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5575    switch (msg->what()) {
5576        case kWhatSetParameters:
5577        case kWhatShutdown:
5578        {
5579            mCodec->deferMessage(msg);
5580            return true;
5581        }
5582
5583        case kWhatResume:
5584        {
5585            // We'll be active soon enough.
5586            return true;
5587        }
5588
5589        case kWhatFlush:
5590        {
5591            // We haven't even started yet, so we're flushed alright...
5592            sp<AMessage> notify = mCodec->mNotify->dup();
5593            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5594            notify->post();
5595
5596            return true;
5597        }
5598
5599        case kWhatSignalEndOfInputStream:
5600        {
5601            mCodec->onSignalEndOfInputStream();
5602            return true;
5603        }
5604
5605        default:
5606            return BaseState::onMessageReceived(msg);
5607    }
5608}
5609
5610bool ACodec::IdleToExecutingState::onOMXEvent(
5611        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5612    switch (event) {
5613        case OMX_EventCmdComplete:
5614        {
5615            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5616            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
5617
5618            mCodec->mExecutingState->resume();
5619            mCodec->changeState(mCodec->mExecutingState);
5620
5621            return true;
5622        }
5623
5624        default:
5625            return BaseState::onOMXEvent(event, data1, data2);
5626    }
5627}
5628
5629////////////////////////////////////////////////////////////////////////////////
5630
5631ACodec::ExecutingState::ExecutingState(ACodec *codec)
5632    : BaseState(codec),
5633      mActive(false) {
5634}
5635
5636ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5637        OMX_U32 /* portIndex */) {
5638    return RESUBMIT_BUFFERS;
5639}
5640
5641void ACodec::ExecutingState::submitOutputMetaBuffers() {
5642    // submit as many buffers as there are input buffers with the codec
5643    // in case we are in port reconfiguring
5644    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5645        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5646
5647        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5648            if (mCodec->submitOutputMetaDataBuffer() != OK)
5649                break;
5650        }
5651    }
5652
5653    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5654    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5655}
5656
5657void ACodec::ExecutingState::submitRegularOutputBuffers() {
5658    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5659        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5660
5661        if (mCodec->mNativeWindow != NULL) {
5662            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5663                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5664
5665            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5666                continue;
5667            }
5668        } else {
5669            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5670        }
5671
5672        ALOGV("[%s] calling fillBuffer %u",
5673             mCodec->mComponentName.c_str(), info->mBufferID);
5674
5675        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5676                 (status_t)OK);
5677
5678        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5679    }
5680}
5681
5682void ACodec::ExecutingState::submitOutputBuffers() {
5683    submitRegularOutputBuffers();
5684    if (mCodec->mStoreMetaDataInOutputBuffers) {
5685        submitOutputMetaBuffers();
5686    }
5687}
5688
5689void ACodec::ExecutingState::resume() {
5690    if (mActive) {
5691        ALOGV("[%s] We're already active, no need to resume.",
5692             mCodec->mComponentName.c_str());
5693
5694        return;
5695    }
5696
5697    submitOutputBuffers();
5698
5699    // Post all available input buffers
5700    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5701    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5702        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5703        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5704            postFillThisBuffer(info);
5705        }
5706    }
5707
5708    mActive = true;
5709}
5710
5711void ACodec::ExecutingState::stateEntered() {
5712    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5713
5714    mCodec->processDeferredMessages();
5715}
5716
5717bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5718    bool handled = false;
5719
5720    switch (msg->what()) {
5721        case kWhatShutdown:
5722        {
5723            int32_t keepComponentAllocated;
5724            CHECK(msg->findInt32(
5725                        "keepComponentAllocated", &keepComponentAllocated));
5726
5727            mCodec->mShutdownInProgress = true;
5728            mCodec->mExplicitShutdown = true;
5729            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5730
5731            mActive = false;
5732
5733            CHECK_EQ(mCodec->mOMX->sendCommand(
5734                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5735                     (status_t)OK);
5736
5737            mCodec->changeState(mCodec->mExecutingToIdleState);
5738
5739            handled = true;
5740            break;
5741        }
5742
5743        case kWhatFlush:
5744        {
5745            ALOGV("[%s] ExecutingState flushing now "
5746                 "(codec owns %zu/%zu input, %zu/%zu output).",
5747                    mCodec->mComponentName.c_str(),
5748                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5749                    mCodec->mBuffers[kPortIndexInput].size(),
5750                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5751                    mCodec->mBuffers[kPortIndexOutput].size());
5752
5753            mActive = false;
5754
5755            CHECK_EQ(mCodec->mOMX->sendCommand(
5756                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5757                     (status_t)OK);
5758
5759            mCodec->changeState(mCodec->mFlushingState);
5760            handled = true;
5761            break;
5762        }
5763
5764        case kWhatResume:
5765        {
5766            resume();
5767
5768            handled = true;
5769            break;
5770        }
5771
5772        case kWhatRequestIDRFrame:
5773        {
5774            status_t err = mCodec->requestIDRFrame();
5775            if (err != OK) {
5776                ALOGW("Requesting an IDR frame failed.");
5777            }
5778
5779            handled = true;
5780            break;
5781        }
5782
5783        case kWhatSetParameters:
5784        {
5785            sp<AMessage> params;
5786            CHECK(msg->findMessage("params", &params));
5787
5788            status_t err = mCodec->setParameters(params);
5789
5790            sp<AMessage> reply;
5791            if (msg->findMessage("reply", &reply)) {
5792                reply->setInt32("err", err);
5793                reply->post();
5794            }
5795
5796            handled = true;
5797            break;
5798        }
5799
5800        case ACodec::kWhatSignalEndOfInputStream:
5801        {
5802            mCodec->onSignalEndOfInputStream();
5803            handled = true;
5804            break;
5805        }
5806
5807        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5808        case kWhatSubmitOutputMetaDataBufferIfEOS:
5809        {
5810            if (mCodec->mPortEOS[kPortIndexInput] &&
5811                    !mCodec->mPortEOS[kPortIndexOutput]) {
5812                status_t err = mCodec->submitOutputMetaDataBuffer();
5813                if (err == OK) {
5814                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5815                }
5816            }
5817            return true;
5818        }
5819
5820        default:
5821            handled = BaseState::onMessageReceived(msg);
5822            break;
5823    }
5824
5825    return handled;
5826}
5827
5828status_t ACodec::setParameters(const sp<AMessage> &params) {
5829    int32_t videoBitrate;
5830    if (params->findInt32("video-bitrate", &videoBitrate)) {
5831        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5832        InitOMXParams(&configParams);
5833        configParams.nPortIndex = kPortIndexOutput;
5834        configParams.nEncodeBitrate = videoBitrate;
5835
5836        status_t err = mOMX->setConfig(
5837                mNode,
5838                OMX_IndexConfigVideoBitrate,
5839                &configParams,
5840                sizeof(configParams));
5841
5842        if (err != OK) {
5843            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5844                   videoBitrate, err);
5845
5846            return err;
5847        }
5848    }
5849
5850    int64_t skipFramesBeforeUs;
5851    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5852        status_t err =
5853            mOMX->setInternalOption(
5854                     mNode,
5855                     kPortIndexInput,
5856                     IOMX::INTERNAL_OPTION_START_TIME,
5857                     &skipFramesBeforeUs,
5858                     sizeof(skipFramesBeforeUs));
5859
5860        if (err != OK) {
5861            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5862            return err;
5863        }
5864    }
5865
5866    int32_t dropInputFrames;
5867    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5868        bool suspend = dropInputFrames != 0;
5869
5870        status_t err =
5871            mOMX->setInternalOption(
5872                     mNode,
5873                     kPortIndexInput,
5874                     IOMX::INTERNAL_OPTION_SUSPEND,
5875                     &suspend,
5876                     sizeof(suspend));
5877
5878        if (err != OK) {
5879            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5880            return err;
5881        }
5882    }
5883
5884    int32_t dummy;
5885    if (params->findInt32("request-sync", &dummy)) {
5886        status_t err = requestIDRFrame();
5887
5888        if (err != OK) {
5889            ALOGE("Requesting a sync frame failed w/ err %d", err);
5890            return err;
5891        }
5892    }
5893
5894    float rate;
5895    if (params->findFloat("operating-rate", &rate) && rate > 0) {
5896        status_t err = setOperatingRate(rate, mIsVideo);
5897        if (err != OK) {
5898            ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
5899            return err;
5900        }
5901    }
5902
5903    return OK;
5904}
5905
5906void ACodec::onSignalEndOfInputStream() {
5907    sp<AMessage> notify = mNotify->dup();
5908    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5909
5910    status_t err = mOMX->signalEndOfInputStream(mNode);
5911    if (err != OK) {
5912        notify->setInt32("err", err);
5913    }
5914    notify->post();
5915}
5916
5917bool ACodec::ExecutingState::onOMXEvent(
5918        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5919    switch (event) {
5920        case OMX_EventPortSettingsChanged:
5921        {
5922            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5923
5924            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5925                mCodec->mMetaDataBuffersToSubmit = 0;
5926                CHECK_EQ(mCodec->mOMX->sendCommand(
5927                            mCodec->mNode,
5928                            OMX_CommandPortDisable, kPortIndexOutput),
5929                         (status_t)OK);
5930
5931                mCodec->freeOutputBuffersNotOwnedByComponent();
5932
5933                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5934            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5935                mCodec->mSentFormat = false;
5936            } else {
5937                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
5938                     mCodec->mComponentName.c_str(), data2);
5939            }
5940
5941            return true;
5942        }
5943
5944        case OMX_EventBufferFlag:
5945        {
5946            return true;
5947        }
5948
5949        default:
5950            return BaseState::onOMXEvent(event, data1, data2);
5951    }
5952}
5953
5954////////////////////////////////////////////////////////////////////////////////
5955
5956ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5957        ACodec *codec)
5958    : BaseState(codec) {
5959}
5960
5961ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5962        OMX_U32 portIndex) {
5963    if (portIndex == kPortIndexOutput) {
5964        return FREE_BUFFERS;
5965    }
5966
5967    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5968
5969    return RESUBMIT_BUFFERS;
5970}
5971
5972bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5973        const sp<AMessage> &msg) {
5974    bool handled = false;
5975
5976    switch (msg->what()) {
5977        case kWhatFlush:
5978        case kWhatShutdown:
5979        case kWhatResume:
5980        case kWhatSetParameters:
5981        {
5982            if (msg->what() == kWhatResume) {
5983                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5984            }
5985
5986            mCodec->deferMessage(msg);
5987            handled = true;
5988            break;
5989        }
5990
5991        default:
5992            handled = BaseState::onMessageReceived(msg);
5993            break;
5994    }
5995
5996    return handled;
5997}
5998
5999void ACodec::OutputPortSettingsChangedState::stateEntered() {
6000    ALOGV("[%s] Now handling output port settings change",
6001         mCodec->mComponentName.c_str());
6002}
6003
6004bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
6005        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6006    switch (event) {
6007        case OMX_EventCmdComplete:
6008        {
6009            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
6010                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
6011
6012                ALOGV("[%s] Output port now disabled.",
6013                        mCodec->mComponentName.c_str());
6014
6015                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
6016                mCodec->mDealer[kPortIndexOutput].clear();
6017
6018                CHECK_EQ(mCodec->mOMX->sendCommand(
6019                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
6020                         (status_t)OK);
6021
6022                status_t err;
6023                if ((err = mCodec->allocateBuffersOnPort(
6024                                kPortIndexOutput)) != OK) {
6025                    ALOGE("Failed to allocate output port buffers after "
6026                         "port reconfiguration (error 0x%08x)",
6027                         err);
6028
6029                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6030
6031                    // This is technically not correct, but appears to be
6032                    // the only way to free the component instance.
6033                    // Controlled transitioning from excecuting->idle
6034                    // and idle->loaded seem impossible probably because
6035                    // the output port never finishes re-enabling.
6036                    mCodec->mShutdownInProgress = true;
6037                    mCodec->mKeepComponentAllocated = false;
6038                    mCodec->changeState(mCodec->mLoadedState);
6039                }
6040
6041                return true;
6042            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
6043                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
6044
6045                mCodec->mSentFormat = false;
6046
6047                ALOGV("[%s] Output port now reenabled.",
6048                        mCodec->mComponentName.c_str());
6049
6050                if (mCodec->mExecutingState->active()) {
6051                    mCodec->mExecutingState->submitOutputBuffers();
6052                }
6053
6054                mCodec->changeState(mCodec->mExecutingState);
6055
6056                return true;
6057            }
6058
6059            return false;
6060        }
6061
6062        default:
6063            return false;
6064    }
6065}
6066
6067////////////////////////////////////////////////////////////////////////////////
6068
6069ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
6070    : BaseState(codec),
6071      mComponentNowIdle(false) {
6072}
6073
6074bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6075    bool handled = false;
6076
6077    switch (msg->what()) {
6078        case kWhatFlush:
6079        {
6080            // Don't send me a flush request if you previously wanted me
6081            // to shutdown.
6082            TRESPASS();
6083            break;
6084        }
6085
6086        case kWhatShutdown:
6087        {
6088            // We're already doing that...
6089
6090            handled = true;
6091            break;
6092        }
6093
6094        default:
6095            handled = BaseState::onMessageReceived(msg);
6096            break;
6097    }
6098
6099    return handled;
6100}
6101
6102void ACodec::ExecutingToIdleState::stateEntered() {
6103    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
6104
6105    mComponentNowIdle = false;
6106    mCodec->mSentFormat = false;
6107}
6108
6109bool ACodec::ExecutingToIdleState::onOMXEvent(
6110        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6111    switch (event) {
6112        case OMX_EventCmdComplete:
6113        {
6114            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
6115            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
6116
6117            mComponentNowIdle = true;
6118
6119            changeStateIfWeOwnAllBuffers();
6120
6121            return true;
6122        }
6123
6124        case OMX_EventPortSettingsChanged:
6125        case OMX_EventBufferFlag:
6126        {
6127            // We're shutting down and don't care about this anymore.
6128            return true;
6129        }
6130
6131        default:
6132            return BaseState::onOMXEvent(event, data1, data2);
6133    }
6134}
6135
6136void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
6137    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
6138        CHECK_EQ(mCodec->mOMX->sendCommand(
6139                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
6140                 (status_t)OK);
6141
6142        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
6143        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
6144
6145        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
6146                && mCodec->mNativeWindow != NULL) {
6147            // We push enough 1x1 blank buffers to ensure that one of
6148            // them has made it to the display.  This allows the OMX
6149            // component teardown to zero out any protected buffers
6150            // without the risk of scanning out one of those buffers.
6151            mCodec->pushBlankBuffersToNativeWindow();
6152        }
6153
6154        mCodec->changeState(mCodec->mIdleToLoadedState);
6155    }
6156}
6157
6158void ACodec::ExecutingToIdleState::onInputBufferFilled(
6159        const sp<AMessage> &msg) {
6160    BaseState::onInputBufferFilled(msg);
6161
6162    changeStateIfWeOwnAllBuffers();
6163}
6164
6165void ACodec::ExecutingToIdleState::onOutputBufferDrained(
6166        const sp<AMessage> &msg) {
6167    BaseState::onOutputBufferDrained(msg);
6168
6169    changeStateIfWeOwnAllBuffers();
6170}
6171
6172////////////////////////////////////////////////////////////////////////////////
6173
6174ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
6175    : BaseState(codec) {
6176}
6177
6178bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
6179    bool handled = false;
6180
6181    switch (msg->what()) {
6182        case kWhatShutdown:
6183        {
6184            // We're already doing that...
6185
6186            handled = true;
6187            break;
6188        }
6189
6190        case kWhatFlush:
6191        {
6192            // Don't send me a flush request if you previously wanted me
6193            // to shutdown.
6194            TRESPASS();
6195            break;
6196        }
6197
6198        default:
6199            handled = BaseState::onMessageReceived(msg);
6200            break;
6201    }
6202
6203    return handled;
6204}
6205
6206void ACodec::IdleToLoadedState::stateEntered() {
6207    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
6208}
6209
6210bool ACodec::IdleToLoadedState::onOMXEvent(
6211        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6212    switch (event) {
6213        case OMX_EventCmdComplete:
6214        {
6215            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
6216            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
6217
6218            mCodec->changeState(mCodec->mLoadedState);
6219
6220            return true;
6221        }
6222
6223        default:
6224            return BaseState::onOMXEvent(event, data1, data2);
6225    }
6226}
6227
6228////////////////////////////////////////////////////////////////////////////////
6229
6230ACodec::FlushingState::FlushingState(ACodec *codec)
6231    : BaseState(codec) {
6232}
6233
6234void ACodec::FlushingState::stateEntered() {
6235    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
6236
6237    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
6238}
6239
6240bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
6241    bool handled = false;
6242
6243    switch (msg->what()) {
6244        case kWhatShutdown:
6245        {
6246            mCodec->deferMessage(msg);
6247            break;
6248        }
6249
6250        case kWhatFlush:
6251        {
6252            // We're already doing this right now.
6253            handled = true;
6254            break;
6255        }
6256
6257        default:
6258            handled = BaseState::onMessageReceived(msg);
6259            break;
6260    }
6261
6262    return handled;
6263}
6264
6265bool ACodec::FlushingState::onOMXEvent(
6266        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6267    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
6268            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
6269
6270    switch (event) {
6271        case OMX_EventCmdComplete:
6272        {
6273            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
6274
6275            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
6276                CHECK(!mFlushComplete[data2]);
6277                mFlushComplete[data2] = true;
6278
6279                if (mFlushComplete[kPortIndexInput]
6280                        && mFlushComplete[kPortIndexOutput]) {
6281                    changeStateIfWeOwnAllBuffers();
6282                }
6283            } else {
6284                CHECK_EQ(data2, OMX_ALL);
6285                CHECK(mFlushComplete[kPortIndexInput]);
6286                CHECK(mFlushComplete[kPortIndexOutput]);
6287
6288                changeStateIfWeOwnAllBuffers();
6289            }
6290
6291            return true;
6292        }
6293
6294        case OMX_EventPortSettingsChanged:
6295        {
6296            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
6297            msg->setInt32("type", omx_message::EVENT);
6298            msg->setInt32("node", mCodec->mNode);
6299            msg->setInt32("event", event);
6300            msg->setInt32("data1", data1);
6301            msg->setInt32("data2", data2);
6302
6303            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
6304                 mCodec->mComponentName.c_str());
6305
6306            mCodec->deferMessage(msg);
6307
6308            return true;
6309        }
6310
6311        default:
6312            return BaseState::onOMXEvent(event, data1, data2);
6313    }
6314
6315    return true;
6316}
6317
6318void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
6319    BaseState::onOutputBufferDrained(msg);
6320
6321    changeStateIfWeOwnAllBuffers();
6322}
6323
6324void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
6325    BaseState::onInputBufferFilled(msg);
6326
6327    changeStateIfWeOwnAllBuffers();
6328}
6329
6330void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
6331    if (mFlushComplete[kPortIndexInput]
6332            && mFlushComplete[kPortIndexOutput]
6333            && mCodec->allYourBuffersAreBelongToUs()) {
6334        // We now own all buffers except possibly those still queued with
6335        // the native window for rendering. Let's get those back as well.
6336        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
6337
6338        sp<AMessage> notify = mCodec->mNotify->dup();
6339        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6340        notify->post();
6341
6342        mCodec->mPortEOS[kPortIndexInput] =
6343            mCodec->mPortEOS[kPortIndexOutput] = false;
6344
6345        mCodec->mInputEOSResult = OK;
6346
6347        if (mCodec->mSkipCutBuffer != NULL) {
6348            mCodec->mSkipCutBuffer->clear();
6349        }
6350
6351        mCodec->changeState(mCodec->mExecutingState);
6352    }
6353}
6354
6355}  // namespace android
6356