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