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