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