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