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