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