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