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