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