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