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