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