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