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