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