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