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