ACodec.cpp revision 13315ce05fbee1e1f5b920cfe4217c3a30167023
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
1639status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1640    int32_t bitrate, iFrameInterval;
1641    if (!msg->findInt32("bitrate", &bitrate)
1642            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1643        return INVALID_OPERATION;
1644    }
1645
1646    float frameRate;
1647    if (!msg->findFloat("frame-rate", &frameRate)) {
1648        int32_t tmp;
1649        if (!msg->findInt32("frame-rate", &tmp)) {
1650            return INVALID_OPERATION;
1651        }
1652        frameRate = (float)tmp;
1653    }
1654
1655    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1656    InitOMXParams(&mpeg4type);
1657    mpeg4type.nPortIndex = kPortIndexOutput;
1658
1659    status_t err = mOMX->getParameter(
1660            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1661
1662    if (err != OK) {
1663        return err;
1664    }
1665
1666    mpeg4type.nSliceHeaderSpacing = 0;
1667    mpeg4type.bSVH = OMX_FALSE;
1668    mpeg4type.bGov = OMX_FALSE;
1669
1670    mpeg4type.nAllowedPictureTypes =
1671        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1672
1673    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1674    if (mpeg4type.nPFrames == 0) {
1675        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1676    }
1677    mpeg4type.nBFrames = 0;
1678    mpeg4type.nIDCVLCThreshold = 0;
1679    mpeg4type.bACPred = OMX_TRUE;
1680    mpeg4type.nMaxPacketSize = 256;
1681    mpeg4type.nTimeIncRes = 1000;
1682    mpeg4type.nHeaderExtension = 0;
1683    mpeg4type.bReversibleVLC = OMX_FALSE;
1684
1685    int32_t profile;
1686    if (msg->findInt32("profile", &profile)) {
1687        int32_t level;
1688        if (!msg->findInt32("level", &level)) {
1689            return INVALID_OPERATION;
1690        }
1691
1692        err = verifySupportForProfileAndLevel(profile, level);
1693
1694        if (err != OK) {
1695            return err;
1696        }
1697
1698        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1699        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1700    }
1701
1702    err = mOMX->setParameter(
1703            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1704
1705    if (err != OK) {
1706        return err;
1707    }
1708
1709    err = configureBitrate(bitrate);
1710
1711    if (err != OK) {
1712        return err;
1713    }
1714
1715    return setupErrorCorrectionParameters();
1716}
1717
1718status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1719    int32_t bitrate, iFrameInterval;
1720    if (!msg->findInt32("bitrate", &bitrate)
1721            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1722        return INVALID_OPERATION;
1723    }
1724
1725    float frameRate;
1726    if (!msg->findFloat("frame-rate", &frameRate)) {
1727        int32_t tmp;
1728        if (!msg->findInt32("frame-rate", &tmp)) {
1729            return INVALID_OPERATION;
1730        }
1731        frameRate = (float)tmp;
1732    }
1733
1734    OMX_VIDEO_PARAM_H263TYPE h263type;
1735    InitOMXParams(&h263type);
1736    h263type.nPortIndex = kPortIndexOutput;
1737
1738    status_t err = mOMX->getParameter(
1739            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1740
1741    if (err != OK) {
1742        return err;
1743    }
1744
1745    h263type.nAllowedPictureTypes =
1746        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1747
1748    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1749    if (h263type.nPFrames == 0) {
1750        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1751    }
1752    h263type.nBFrames = 0;
1753
1754    int32_t profile;
1755    if (msg->findInt32("profile", &profile)) {
1756        int32_t level;
1757        if (!msg->findInt32("level", &level)) {
1758            return INVALID_OPERATION;
1759        }
1760
1761        err = verifySupportForProfileAndLevel(profile, level);
1762
1763        if (err != OK) {
1764            return err;
1765        }
1766
1767        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1768        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1769    }
1770
1771    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1772    h263type.bForceRoundingTypeToZero = OMX_FALSE;
1773    h263type.nPictureHeaderRepetition = 0;
1774    h263type.nGOBHeaderInterval = 0;
1775
1776    err = mOMX->setParameter(
1777            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1778
1779    if (err != OK) {
1780        return err;
1781    }
1782
1783    err = configureBitrate(bitrate);
1784
1785    if (err != OK) {
1786        return err;
1787    }
1788
1789    return setupErrorCorrectionParameters();
1790}
1791
1792status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1793    int32_t bitrate, iFrameInterval;
1794    if (!msg->findInt32("bitrate", &bitrate)
1795            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1796        return INVALID_OPERATION;
1797    }
1798
1799    float frameRate;
1800    if (!msg->findFloat("frame-rate", &frameRate)) {
1801        int32_t tmp;
1802        if (!msg->findInt32("frame-rate", &tmp)) {
1803            return INVALID_OPERATION;
1804        }
1805        frameRate = (float)tmp;
1806    }
1807
1808    OMX_VIDEO_PARAM_AVCTYPE h264type;
1809    InitOMXParams(&h264type);
1810    h264type.nPortIndex = kPortIndexOutput;
1811
1812    status_t err = mOMX->getParameter(
1813            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1814
1815    if (err != OK) {
1816        return err;
1817    }
1818
1819    h264type.nAllowedPictureTypes =
1820        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1821
1822    int32_t profile;
1823    if (msg->findInt32("profile", &profile)) {
1824        int32_t level;
1825        if (!msg->findInt32("level", &level)) {
1826            return INVALID_OPERATION;
1827        }
1828
1829        err = verifySupportForProfileAndLevel(profile, level);
1830
1831        if (err != OK) {
1832            return err;
1833        }
1834
1835        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
1836        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
1837    }
1838
1839    // XXX
1840    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
1841        ALOGW("Use baseline profile instead of %d for AVC recording",
1842            h264type.eProfile);
1843        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1844    }
1845
1846    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1847        h264type.nSliceHeaderSpacing = 0;
1848        h264type.bUseHadamard = OMX_TRUE;
1849        h264type.nRefFrames = 1;
1850        h264type.nBFrames = 0;
1851        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1852        if (h264type.nPFrames == 0) {
1853            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1854        }
1855        h264type.nRefIdx10ActiveMinus1 = 0;
1856        h264type.nRefIdx11ActiveMinus1 = 0;
1857        h264type.bEntropyCodingCABAC = OMX_FALSE;
1858        h264type.bWeightedPPrediction = OMX_FALSE;
1859        h264type.bconstIpred = OMX_FALSE;
1860        h264type.bDirect8x8Inference = OMX_FALSE;
1861        h264type.bDirectSpatialTemporal = OMX_FALSE;
1862        h264type.nCabacInitIdc = 0;
1863    }
1864
1865    if (h264type.nBFrames != 0) {
1866        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1867    }
1868
1869    h264type.bEnableUEP = OMX_FALSE;
1870    h264type.bEnableFMO = OMX_FALSE;
1871    h264type.bEnableASO = OMX_FALSE;
1872    h264type.bEnableRS = OMX_FALSE;
1873    h264type.bFrameMBsOnly = OMX_TRUE;
1874    h264type.bMBAFF = OMX_FALSE;
1875    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1876
1877    err = mOMX->setParameter(
1878            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1879
1880    if (err != OK) {
1881        return err;
1882    }
1883
1884    return configureBitrate(bitrate);
1885}
1886
1887status_t ACodec::verifySupportForProfileAndLevel(
1888        int32_t profile, int32_t level) {
1889    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
1890    InitOMXParams(&params);
1891    params.nPortIndex = kPortIndexOutput;
1892
1893    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1894        status_t err = mOMX->getParameter(
1895                mNode,
1896                OMX_IndexParamVideoProfileLevelQuerySupported,
1897                &params,
1898                sizeof(params));
1899
1900        if (err != OK) {
1901            return err;
1902        }
1903
1904        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
1905        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
1906
1907        if (profile == supportedProfile && level <= supportedLevel) {
1908            return OK;
1909        }
1910    }
1911}
1912
1913status_t ACodec::configureBitrate(int32_t bitrate) {
1914    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1915    InitOMXParams(&bitrateType);
1916    bitrateType.nPortIndex = kPortIndexOutput;
1917
1918    status_t err = mOMX->getParameter(
1919            mNode, OMX_IndexParamVideoBitrate,
1920            &bitrateType, sizeof(bitrateType));
1921
1922    if (err != OK) {
1923        return err;
1924    }
1925
1926    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1927    bitrateType.nTargetBitrate = bitrate;
1928
1929    return mOMX->setParameter(
1930            mNode, OMX_IndexParamVideoBitrate,
1931            &bitrateType, sizeof(bitrateType));
1932}
1933
1934status_t ACodec::setupErrorCorrectionParameters() {
1935    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1936    InitOMXParams(&errorCorrectionType);
1937    errorCorrectionType.nPortIndex = kPortIndexOutput;
1938
1939    status_t err = mOMX->getParameter(
1940            mNode, OMX_IndexParamVideoErrorCorrection,
1941            &errorCorrectionType, sizeof(errorCorrectionType));
1942
1943    if (err != OK) {
1944        return OK;  // Optional feature. Ignore this failure
1945    }
1946
1947    errorCorrectionType.bEnableHEC = OMX_FALSE;
1948    errorCorrectionType.bEnableResync = OMX_TRUE;
1949    errorCorrectionType.nResynchMarkerSpacing = 256;
1950    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1951    errorCorrectionType.bEnableRVLC = OMX_FALSE;
1952
1953    return mOMX->setParameter(
1954            mNode, OMX_IndexParamVideoErrorCorrection,
1955            &errorCorrectionType, sizeof(errorCorrectionType));
1956}
1957
1958status_t ACodec::setVideoFormatOnPort(
1959        OMX_U32 portIndex,
1960        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1961    OMX_PARAM_PORTDEFINITIONTYPE def;
1962    InitOMXParams(&def);
1963    def.nPortIndex = portIndex;
1964
1965    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1966
1967    status_t err = mOMX->getParameter(
1968            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1969
1970    CHECK_EQ(err, (status_t)OK);
1971
1972    if (portIndex == kPortIndexInput) {
1973        // XXX Need a (much) better heuristic to compute input buffer sizes.
1974        const size_t X = 64 * 1024;
1975        if (def.nBufferSize < X) {
1976            def.nBufferSize = X;
1977        }
1978    }
1979
1980    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1981
1982    video_def->nFrameWidth = width;
1983    video_def->nFrameHeight = height;
1984
1985    if (portIndex == kPortIndexInput) {
1986        video_def->eCompressionFormat = compressionFormat;
1987        video_def->eColorFormat = OMX_COLOR_FormatUnused;
1988    }
1989
1990    err = mOMX->setParameter(
1991            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1992
1993    return err;
1994}
1995
1996status_t ACodec::initNativeWindow() {
1997    if (mNativeWindow != NULL) {
1998        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1999    }
2000
2001    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
2002    return OK;
2003}
2004
2005size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
2006    size_t n = 0;
2007
2008    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2009        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
2010
2011        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
2012            ++n;
2013        }
2014    }
2015
2016    return n;
2017}
2018
2019bool ACodec::allYourBuffersAreBelongToUs(
2020        OMX_U32 portIndex) {
2021    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2022        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
2023
2024        if (info->mStatus != BufferInfo::OWNED_BY_US
2025                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2026            ALOGV("[%s] Buffer %p on port %ld still has status %d",
2027                    mComponentName.c_str(),
2028                    info->mBufferID, portIndex, info->mStatus);
2029            return false;
2030        }
2031    }
2032
2033    return true;
2034}
2035
2036bool ACodec::allYourBuffersAreBelongToUs() {
2037    return allYourBuffersAreBelongToUs(kPortIndexInput)
2038        && allYourBuffersAreBelongToUs(kPortIndexOutput);
2039}
2040
2041void ACodec::deferMessage(const sp<AMessage> &msg) {
2042    bool wasEmptyBefore = mDeferredQueue.empty();
2043    mDeferredQueue.push_back(msg);
2044}
2045
2046void ACodec::processDeferredMessages() {
2047    List<sp<AMessage> > queue = mDeferredQueue;
2048    mDeferredQueue.clear();
2049
2050    List<sp<AMessage> >::iterator it = queue.begin();
2051    while (it != queue.end()) {
2052        onMessageReceived(*it++);
2053    }
2054}
2055
2056void ACodec::sendFormatChange() {
2057    sp<AMessage> notify = mNotify->dup();
2058    notify->setInt32("what", kWhatOutputFormatChanged);
2059
2060    OMX_PARAM_PORTDEFINITIONTYPE def;
2061    InitOMXParams(&def);
2062    def.nPortIndex = kPortIndexOutput;
2063
2064    CHECK_EQ(mOMX->getParameter(
2065                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
2066             (status_t)OK);
2067
2068    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
2069
2070    switch (def.eDomain) {
2071        case OMX_PortDomainVideo:
2072        {
2073            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2074
2075            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
2076            notify->setInt32("width", videoDef->nFrameWidth);
2077            notify->setInt32("height", videoDef->nFrameHeight);
2078            notify->setInt32("stride", videoDef->nStride);
2079            notify->setInt32("slice-height", videoDef->nSliceHeight);
2080            notify->setInt32("color-format", videoDef->eColorFormat);
2081
2082            OMX_CONFIG_RECTTYPE rect;
2083            InitOMXParams(&rect);
2084            rect.nPortIndex = kPortIndexOutput;
2085
2086            if (mOMX->getConfig(
2087                        mNode, OMX_IndexConfigCommonOutputCrop,
2088                        &rect, sizeof(rect)) != OK) {
2089                rect.nLeft = 0;
2090                rect.nTop = 0;
2091                rect.nWidth = videoDef->nFrameWidth;
2092                rect.nHeight = videoDef->nFrameHeight;
2093            }
2094
2095            CHECK_GE(rect.nLeft, 0);
2096            CHECK_GE(rect.nTop, 0);
2097            CHECK_GE(rect.nWidth, 0u);
2098            CHECK_GE(rect.nHeight, 0u);
2099            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
2100            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
2101
2102            notify->setRect(
2103                    "crop",
2104                    rect.nLeft,
2105                    rect.nTop,
2106                    rect.nLeft + rect.nWidth - 1,
2107                    rect.nTop + rect.nHeight - 1);
2108
2109            if (mNativeWindow != NULL) {
2110                android_native_rect_t crop;
2111                crop.left = rect.nLeft;
2112                crop.top = rect.nTop;
2113                crop.right = rect.nLeft + rect.nWidth;
2114                crop.bottom = rect.nTop + rect.nHeight;
2115
2116                CHECK_EQ(0, native_window_set_crop(
2117                            mNativeWindow.get(), &crop));
2118            }
2119            break;
2120        }
2121
2122        case OMX_PortDomainAudio:
2123        {
2124            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2125            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
2126
2127            OMX_AUDIO_PARAM_PCMMODETYPE params;
2128            InitOMXParams(&params);
2129            params.nPortIndex = kPortIndexOutput;
2130
2131            CHECK_EQ(mOMX->getParameter(
2132                        mNode, OMX_IndexParamAudioPcm,
2133                        &params, sizeof(params)),
2134                     (status_t)OK);
2135
2136            CHECK(params.nChannels == 1 || params.bInterleaved);
2137            CHECK_EQ(params.nBitPerSample, 16u);
2138            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
2139            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
2140
2141            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2142            notify->setInt32("channel-count", params.nChannels);
2143            notify->setInt32("sample-rate", params.nSamplingRate);
2144            if (mEncoderDelay + mEncoderPadding) {
2145                size_t frameSize = params.nChannels * sizeof(int16_t);
2146                if (mSkipCutBuffer != NULL) {
2147                    size_t prevbufsize = mSkipCutBuffer->size();
2148                    if (prevbufsize != 0) {
2149                        ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize);
2150                    }
2151                }
2152                mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize,
2153                                                   mEncoderPadding * frameSize);
2154            }
2155
2156            if (mChannelMaskPresent) {
2157                notify->setInt32("channel-mask", mChannelMask);
2158            }
2159
2160            break;
2161        }
2162
2163        default:
2164            TRESPASS();
2165    }
2166
2167    notify->post();
2168
2169    mSentFormat = true;
2170}
2171
2172void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2173    sp<AMessage> notify = mNotify->dup();
2174    notify->setInt32("what", ACodec::kWhatError);
2175    notify->setInt32("omx-error", error);
2176    notify->setInt32("err", internalError);
2177    notify->post();
2178}
2179
2180status_t ACodec::pushBlankBuffersToNativeWindow() {
2181    status_t err = NO_ERROR;
2182    ANativeWindowBuffer* anb = NULL;
2183    int numBufs = 0;
2184    int minUndequeuedBufs = 0;
2185
2186    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2187    // no frames get dropped by SurfaceFlinger assuming that these are video
2188    // frames.
2189    err = native_window_api_disconnect(mNativeWindow.get(),
2190            NATIVE_WINDOW_API_MEDIA);
2191    if (err != NO_ERROR) {
2192        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2193                strerror(-err), -err);
2194        return err;
2195    }
2196
2197    err = native_window_api_connect(mNativeWindow.get(),
2198            NATIVE_WINDOW_API_CPU);
2199    if (err != NO_ERROR) {
2200        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2201                strerror(-err), -err);
2202        return err;
2203    }
2204
2205    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2206            HAL_PIXEL_FORMAT_RGBX_8888);
2207    if (err != NO_ERROR) {
2208        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2209                strerror(-err), -err);
2210        goto error;
2211    }
2212
2213    err = native_window_set_usage(mNativeWindow.get(),
2214            GRALLOC_USAGE_SW_WRITE_OFTEN);
2215    if (err != NO_ERROR) {
2216        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
2217                strerror(-err), -err);
2218        goto error;
2219    }
2220
2221    err = mNativeWindow->query(mNativeWindow.get(),
2222            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2223    if (err != NO_ERROR) {
2224        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2225                "failed: %s (%d)", strerror(-err), -err);
2226        goto error;
2227    }
2228
2229    numBufs = minUndequeuedBufs + 1;
2230    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2231    if (err != NO_ERROR) {
2232        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2233                strerror(-err), -err);
2234        goto error;
2235    }
2236
2237    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
2238    // buffer twice.  This should guarantee that the buffer has been displayed
2239    // on the screen and then been replaced, so an previous video frames are
2240    // guaranteed NOT to be currently displayed.
2241    for (int i = 0; i < numBufs + 1; i++) {
2242        int fenceFd = -1;
2243        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
2244        if (err != NO_ERROR) {
2245            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2246                    strerror(-err), -err);
2247            goto error;
2248        }
2249
2250        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2251
2252        // Fill the buffer with the a 1x1 checkerboard pattern ;)
2253        uint32_t* img = NULL;
2254        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2255        if (err != NO_ERROR) {
2256            ALOGE("error pushing blank frames: lock failed: %s (%d)",
2257                    strerror(-err), -err);
2258            goto error;
2259        }
2260
2261        *img = 0;
2262
2263        err = buf->unlock();
2264        if (err != NO_ERROR) {
2265            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
2266                    strerror(-err), -err);
2267            goto error;
2268        }
2269
2270        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2271                buf->getNativeBuffer(), -1);
2272        if (err != NO_ERROR) {
2273            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2274                    strerror(-err), -err);
2275            goto error;
2276        }
2277
2278        anb = NULL;
2279    }
2280
2281error:
2282
2283    if (err != NO_ERROR) {
2284        // Clean up after an error.
2285        if (anb != NULL) {
2286            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
2287        }
2288
2289        native_window_api_disconnect(mNativeWindow.get(),
2290                NATIVE_WINDOW_API_CPU);
2291        native_window_api_connect(mNativeWindow.get(),
2292                NATIVE_WINDOW_API_MEDIA);
2293
2294        return err;
2295    } else {
2296        // Clean up after success.
2297        err = native_window_api_disconnect(mNativeWindow.get(),
2298                NATIVE_WINDOW_API_CPU);
2299        if (err != NO_ERROR) {
2300            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2301                    strerror(-err), -err);
2302            return err;
2303        }
2304
2305        err = native_window_api_connect(mNativeWindow.get(),
2306                NATIVE_WINDOW_API_MEDIA);
2307        if (err != NO_ERROR) {
2308            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2309                    strerror(-err), -err);
2310            return err;
2311        }
2312
2313        return NO_ERROR;
2314    }
2315}
2316
2317////////////////////////////////////////////////////////////////////////////////
2318
2319ACodec::PortDescription::PortDescription() {
2320}
2321
2322status_t ACodec::requestIDRFrame() {
2323    if (!mIsEncoder) {
2324        return ERROR_UNSUPPORTED;
2325    }
2326
2327    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
2328    InitOMXParams(&params);
2329
2330    params.nPortIndex = kPortIndexOutput;
2331    params.IntraRefreshVOP = OMX_TRUE;
2332
2333    return mOMX->setConfig(
2334            mNode,
2335            OMX_IndexConfigVideoIntraVOPRefresh,
2336            &params,
2337            sizeof(params));
2338}
2339
2340void ACodec::PortDescription::addBuffer(
2341        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
2342    mBufferIDs.push_back(id);
2343    mBuffers.push_back(buffer);
2344}
2345
2346size_t ACodec::PortDescription::countBuffers() {
2347    return mBufferIDs.size();
2348}
2349
2350IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
2351    return mBufferIDs.itemAt(index);
2352}
2353
2354sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
2355    return mBuffers.itemAt(index);
2356}
2357
2358////////////////////////////////////////////////////////////////////////////////
2359
2360ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2361    : AState(parentState),
2362      mCodec(codec) {
2363}
2364
2365ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2366    return KEEP_BUFFERS;
2367}
2368
2369bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2370    switch (msg->what()) {
2371        case kWhatInputBufferFilled:
2372        {
2373            onInputBufferFilled(msg);
2374            break;
2375        }
2376
2377        case kWhatOutputBufferDrained:
2378        {
2379            onOutputBufferDrained(msg);
2380            break;
2381        }
2382
2383        case ACodec::kWhatOMXMessage:
2384        {
2385            return onOMXMessage(msg);
2386        }
2387
2388        default:
2389            return false;
2390    }
2391
2392    return true;
2393}
2394
2395bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2396    int32_t type;
2397    CHECK(msg->findInt32("type", &type));
2398
2399    IOMX::node_id nodeID;
2400    CHECK(msg->findPointer("node", &nodeID));
2401    CHECK_EQ(nodeID, mCodec->mNode);
2402
2403    switch (type) {
2404        case omx_message::EVENT:
2405        {
2406            int32_t event, data1, data2;
2407            CHECK(msg->findInt32("event", &event));
2408            CHECK(msg->findInt32("data1", &data1));
2409            CHECK(msg->findInt32("data2", &data2));
2410
2411            if (event == OMX_EventCmdComplete
2412                    && data1 == OMX_CommandFlush
2413                    && data2 == (int32_t)OMX_ALL) {
2414                // Use of this notification is not consistent across
2415                // implementations. We'll drop this notification and rely
2416                // on flush-complete notifications on the individual port
2417                // indices instead.
2418
2419                return true;
2420            }
2421
2422            return onOMXEvent(
2423                    static_cast<OMX_EVENTTYPE>(event),
2424                    static_cast<OMX_U32>(data1),
2425                    static_cast<OMX_U32>(data2));
2426        }
2427
2428        case omx_message::EMPTY_BUFFER_DONE:
2429        {
2430            IOMX::buffer_id bufferID;
2431            CHECK(msg->findPointer("buffer", &bufferID));
2432
2433            return onOMXEmptyBufferDone(bufferID);
2434        }
2435
2436        case omx_message::FILL_BUFFER_DONE:
2437        {
2438            IOMX::buffer_id bufferID;
2439            CHECK(msg->findPointer("buffer", &bufferID));
2440
2441            int32_t rangeOffset, rangeLength, flags;
2442            int64_t timeUs;
2443            void *platformPrivate;
2444            void *dataPtr;
2445
2446            CHECK(msg->findInt32("range_offset", &rangeOffset));
2447            CHECK(msg->findInt32("range_length", &rangeLength));
2448            CHECK(msg->findInt32("flags", &flags));
2449            CHECK(msg->findInt64("timestamp", &timeUs));
2450            CHECK(msg->findPointer("platform_private", &platformPrivate));
2451            CHECK(msg->findPointer("data_ptr", &dataPtr));
2452
2453            return onOMXFillBufferDone(
2454                    bufferID,
2455                    (size_t)rangeOffset, (size_t)rangeLength,
2456                    (OMX_U32)flags,
2457                    timeUs,
2458                    platformPrivate,
2459                    dataPtr);
2460        }
2461
2462        default:
2463            TRESPASS();
2464            break;
2465    }
2466}
2467
2468bool ACodec::BaseState::onOMXEvent(
2469        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2470    if (event != OMX_EventError) {
2471        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
2472             mCodec->mComponentName.c_str(), event, data1, data2);
2473
2474        return false;
2475    }
2476
2477    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
2478
2479    mCodec->signalError((OMX_ERRORTYPE)data1);
2480
2481    return true;
2482}
2483
2484bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
2485    ALOGV("[%s] onOMXEmptyBufferDone %p",
2486         mCodec->mComponentName.c_str(), bufferID);
2487
2488    BufferInfo *info =
2489        mCodec->findBufferByID(kPortIndexInput, bufferID);
2490
2491    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2492    info->mStatus = BufferInfo::OWNED_BY_US;
2493
2494    const sp<AMessage> &bufferMeta = info->mData->meta();
2495    void *mediaBuffer;
2496    if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer)
2497            && mediaBuffer != NULL) {
2498        // We're in "store-metadata-in-buffers" mode, the underlying
2499        // OMX component had access to data that's implicitly refcounted
2500        // by this "mediaBuffer" object. Now that the OMX component has
2501        // told us that it's done with the input buffer, we can decrement
2502        // the mediaBuffer's reference count.
2503
2504        ALOGV("releasing mbuf %p", mediaBuffer);
2505
2506        ((MediaBuffer *)mediaBuffer)->release();
2507        mediaBuffer = NULL;
2508
2509        bufferMeta->setPointer("mediaBuffer", NULL);
2510    }
2511
2512    PortMode mode = getPortMode(kPortIndexInput);
2513
2514    switch (mode) {
2515        case KEEP_BUFFERS:
2516            break;
2517
2518        case RESUBMIT_BUFFERS:
2519            postFillThisBuffer(info);
2520            break;
2521
2522        default:
2523        {
2524            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2525            TRESPASS();  // Not currently used
2526            break;
2527        }
2528    }
2529
2530    return true;
2531}
2532
2533void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2534    if (mCodec->mPortEOS[kPortIndexInput]) {
2535        return;
2536    }
2537
2538    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2539
2540    sp<AMessage> notify = mCodec->mNotify->dup();
2541    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2542    notify->setPointer("buffer-id", info->mBufferID);
2543
2544    info->mData->meta()->clear();
2545    notify->setBuffer("buffer", info->mData);
2546
2547    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2548    reply->setPointer("buffer-id", info->mBufferID);
2549
2550    notify->setMessage("reply", reply);
2551
2552    notify->post();
2553
2554    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2555}
2556
2557void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2558    IOMX::buffer_id bufferID;
2559    CHECK(msg->findPointer("buffer-id", &bufferID));
2560
2561    sp<ABuffer> buffer;
2562    int32_t err = OK;
2563    bool eos = false;
2564
2565    if (!msg->findBuffer("buffer", &buffer)) {
2566        CHECK(msg->findInt32("err", &err));
2567
2568        ALOGV("[%s] saw error %d instead of an input buffer",
2569             mCodec->mComponentName.c_str(), err);
2570
2571        buffer.clear();
2572
2573        eos = true;
2574    }
2575
2576    int32_t tmp;
2577    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2578        eos = true;
2579        err = ERROR_END_OF_STREAM;
2580    }
2581
2582    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2583    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2584
2585    info->mStatus = BufferInfo::OWNED_BY_US;
2586
2587    PortMode mode = getPortMode(kPortIndexInput);
2588
2589    switch (mode) {
2590        case KEEP_BUFFERS:
2591        {
2592            if (eos) {
2593                if (!mCodec->mPortEOS[kPortIndexInput]) {
2594                    mCodec->mPortEOS[kPortIndexInput] = true;
2595                    mCodec->mInputEOSResult = err;
2596                }
2597            }
2598            break;
2599        }
2600
2601        case RESUBMIT_BUFFERS:
2602        {
2603            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2604                int64_t timeUs;
2605                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2606
2607                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2608
2609                int32_t isCSD;
2610                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2611                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
2612                }
2613
2614                if (eos) {
2615                    flags |= OMX_BUFFERFLAG_EOS;
2616                }
2617
2618                if (buffer != info->mData) {
2619                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
2620                         mCodec->mComponentName.c_str(),
2621                         bufferID,
2622                         buffer.get(), info->mData.get());
2623
2624                    CHECK_LE(buffer->size(), info->mData->capacity());
2625                    memcpy(info->mData->data(), buffer->data(), buffer->size());
2626                }
2627
2628                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2629                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2630                         mCodec->mComponentName.c_str(), bufferID);
2631                } else if (flags & OMX_BUFFERFLAG_EOS) {
2632                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2633                         mCodec->mComponentName.c_str(), bufferID);
2634                } else {
2635#if TRACK_BUFFER_TIMING
2636                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
2637                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2638#else
2639                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2640                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2641#endif
2642                }
2643
2644#if TRACK_BUFFER_TIMING
2645                ACodec::BufferStats stats;
2646                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
2647                stats.mFillBufferDoneTimeUs = -1ll;
2648                mCodec->mBufferStats.add(timeUs, stats);
2649#endif
2650
2651                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2652                            mCodec->mNode,
2653                            bufferID,
2654                            0,
2655                            buffer->size(),
2656                            flags,
2657                            timeUs),
2658                         (status_t)OK);
2659
2660                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2661
2662                if (!eos) {
2663                    getMoreInputDataIfPossible();
2664                } else {
2665                    ALOGV("[%s] Signalled EOS on the input port",
2666                         mCodec->mComponentName.c_str());
2667
2668                    mCodec->mPortEOS[kPortIndexInput] = true;
2669                    mCodec->mInputEOSResult = err;
2670                }
2671            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2672                if (err != ERROR_END_OF_STREAM) {
2673                    ALOGV("[%s] Signalling EOS on the input port "
2674                         "due to error %d",
2675                         mCodec->mComponentName.c_str(), err);
2676                } else {
2677                    ALOGV("[%s] Signalling EOS on the input port",
2678                         mCodec->mComponentName.c_str());
2679                }
2680
2681                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2682                     mCodec->mComponentName.c_str(), bufferID);
2683
2684                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2685                            mCodec->mNode,
2686                            bufferID,
2687                            0,
2688                            0,
2689                            OMX_BUFFERFLAG_EOS,
2690                            0),
2691                         (status_t)OK);
2692
2693                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2694
2695                mCodec->mPortEOS[kPortIndexInput] = true;
2696                mCodec->mInputEOSResult = err;
2697            }
2698            break;
2699
2700            default:
2701                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2702                break;
2703        }
2704    }
2705}
2706
2707void ACodec::BaseState::getMoreInputDataIfPossible() {
2708    if (mCodec->mPortEOS[kPortIndexInput]) {
2709        return;
2710    }
2711
2712    BufferInfo *eligible = NULL;
2713
2714    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2715        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2716
2717#if 0
2718        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2719            // There's already a "read" pending.
2720            return;
2721        }
2722#endif
2723
2724        if (info->mStatus == BufferInfo::OWNED_BY_US) {
2725            eligible = info;
2726        }
2727    }
2728
2729    if (eligible == NULL) {
2730        return;
2731    }
2732
2733    postFillThisBuffer(eligible);
2734}
2735
2736bool ACodec::BaseState::onOMXFillBufferDone(
2737        IOMX::buffer_id bufferID,
2738        size_t rangeOffset, size_t rangeLength,
2739        OMX_U32 flags,
2740        int64_t timeUs,
2741        void *platformPrivate,
2742        void *dataPtr) {
2743    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2744         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
2745
2746    ssize_t index;
2747
2748#if TRACK_BUFFER_TIMING
2749    index = mCodec->mBufferStats.indexOfKey(timeUs);
2750    if (index >= 0) {
2751        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
2752        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
2753
2754        ALOGI("frame PTS %lld: %lld",
2755                timeUs,
2756                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
2757
2758        mCodec->mBufferStats.removeItemsAt(index);
2759        stats = NULL;
2760    }
2761#endif
2762
2763    BufferInfo *info =
2764        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2765
2766    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2767
2768    info->mStatus = BufferInfo::OWNED_BY_US;
2769
2770    PortMode mode = getPortMode(kPortIndexOutput);
2771
2772    switch (mode) {
2773        case KEEP_BUFFERS:
2774            break;
2775
2776        case RESUBMIT_BUFFERS:
2777        {
2778            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2779                ALOGV("[%s] calling fillBuffer %p",
2780                     mCodec->mComponentName.c_str(), info->mBufferID);
2781
2782                CHECK_EQ(mCodec->mOMX->fillBuffer(
2783                            mCodec->mNode, info->mBufferID),
2784                         (status_t)OK);
2785
2786                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2787                break;
2788            }
2789
2790            if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2791                mCodec->sendFormatChange();
2792            }
2793
2794            if (mCodec->mNativeWindow == NULL) {
2795                info->mData->setRange(rangeOffset, rangeLength);
2796
2797#if 0
2798                if (IsIDR(info->mData)) {
2799                    ALOGI("IDR frame");
2800                }
2801#endif
2802            }
2803
2804            if (mCodec->mSkipCutBuffer != NULL) {
2805                mCodec->mSkipCutBuffer->submit(info->mData);
2806            }
2807            info->mData->meta()->setInt64("timeUs", timeUs);
2808
2809            sp<AMessage> notify = mCodec->mNotify->dup();
2810            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2811            notify->setPointer("buffer-id", info->mBufferID);
2812            notify->setBuffer("buffer", info->mData);
2813            notify->setInt32("flags", flags);
2814
2815            sp<AMessage> reply =
2816                new AMessage(kWhatOutputBufferDrained, mCodec->id());
2817
2818            reply->setPointer("buffer-id", info->mBufferID);
2819
2820            notify->setMessage("reply", reply);
2821
2822            notify->post();
2823
2824            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2825
2826            if (flags & OMX_BUFFERFLAG_EOS) {
2827                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2828
2829                sp<AMessage> notify = mCodec->mNotify->dup();
2830                notify->setInt32("what", ACodec::kWhatEOS);
2831                notify->setInt32("err", mCodec->mInputEOSResult);
2832                notify->post();
2833
2834                mCodec->mPortEOS[kPortIndexOutput] = true;
2835            }
2836            break;
2837        }
2838
2839        default:
2840        {
2841            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2842
2843            CHECK_EQ((status_t)OK,
2844                     mCodec->freeBuffer(kPortIndexOutput, index));
2845            break;
2846        }
2847    }
2848
2849    return true;
2850}
2851
2852void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2853    IOMX::buffer_id bufferID;
2854    CHECK(msg->findPointer("buffer-id", &bufferID));
2855
2856    ssize_t index;
2857    BufferInfo *info =
2858        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2859    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2860
2861    int32_t render;
2862    if (mCodec->mNativeWindow != NULL
2863            && msg->findInt32("render", &render) && render != 0) {
2864        // The client wants this buffer to be rendered.
2865
2866        status_t err;
2867        if ((err = mCodec->mNativeWindow->queueBuffer(
2868                    mCodec->mNativeWindow.get(),
2869                    info->mGraphicBuffer.get(), -1)) == OK) {
2870            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2871        } else {
2872            mCodec->signalError(OMX_ErrorUndefined, err);
2873            info->mStatus = BufferInfo::OWNED_BY_US;
2874        }
2875    } else {
2876        info->mStatus = BufferInfo::OWNED_BY_US;
2877    }
2878
2879    PortMode mode = getPortMode(kPortIndexOutput);
2880
2881    switch (mode) {
2882        case KEEP_BUFFERS:
2883        {
2884            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2885
2886            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2887                // We cannot resubmit the buffer we just rendered, dequeue
2888                // the spare instead.
2889
2890                info = mCodec->dequeueBufferFromNativeWindow();
2891            }
2892            break;
2893        }
2894
2895        case RESUBMIT_BUFFERS:
2896        {
2897            if (!mCodec->mPortEOS[kPortIndexOutput]) {
2898                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2899                    // We cannot resubmit the buffer we just rendered, dequeue
2900                    // the spare instead.
2901
2902                    info = mCodec->dequeueBufferFromNativeWindow();
2903                }
2904
2905                if (info != NULL) {
2906                    ALOGV("[%s] calling fillBuffer %p",
2907                         mCodec->mComponentName.c_str(), info->mBufferID);
2908
2909                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2910                             (status_t)OK);
2911
2912                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2913                }
2914            }
2915            break;
2916        }
2917
2918        default:
2919        {
2920            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2921
2922            CHECK_EQ((status_t)OK,
2923                     mCodec->freeBuffer(kPortIndexOutput, index));
2924            break;
2925        }
2926    }
2927}
2928
2929////////////////////////////////////////////////////////////////////////////////
2930
2931ACodec::UninitializedState::UninitializedState(ACodec *codec)
2932    : BaseState(codec) {
2933}
2934
2935void ACodec::UninitializedState::stateEntered() {
2936    ALOGV("Now uninitialized");
2937}
2938
2939bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2940    bool handled = false;
2941
2942    switch (msg->what()) {
2943        case ACodec::kWhatSetup:
2944        {
2945            onSetup(msg);
2946
2947            handled = true;
2948            break;
2949        }
2950
2951        case ACodec::kWhatAllocateComponent:
2952        {
2953            onAllocateComponent(msg);
2954            handled = true;
2955            break;
2956        }
2957
2958        case ACodec::kWhatShutdown:
2959        {
2960            int32_t keepComponentAllocated;
2961            CHECK(msg->findInt32(
2962                        "keepComponentAllocated", &keepComponentAllocated));
2963            CHECK(!keepComponentAllocated);
2964
2965            sp<AMessage> notify = mCodec->mNotify->dup();
2966            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2967            notify->post();
2968
2969            handled = true;
2970            break;
2971        }
2972
2973        case ACodec::kWhatFlush:
2974        {
2975            sp<AMessage> notify = mCodec->mNotify->dup();
2976            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2977            notify->post();
2978
2979            handled = true;
2980            break;
2981        }
2982
2983        default:
2984            return BaseState::onMessageReceived(msg);
2985    }
2986
2987    return handled;
2988}
2989
2990void ACodec::UninitializedState::onSetup(
2991        const sp<AMessage> &msg) {
2992    if (onAllocateComponent(msg)
2993            && mCodec->mLoadedState->onConfigureComponent(msg)) {
2994        mCodec->mLoadedState->onStart();
2995    }
2996}
2997
2998bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
2999    ALOGV("onAllocateComponent");
3000
3001    CHECK(mCodec->mNode == NULL);
3002
3003    OMXClient client;
3004    CHECK_EQ(client.connect(), (status_t)OK);
3005
3006    sp<IOMX> omx = client.interface();
3007
3008    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
3009
3010    AString mime;
3011
3012    AString componentName;
3013    uint32_t quirks = 0;
3014    if (msg->findString("componentName", &componentName)) {
3015        ssize_t index = matchingCodecs.add();
3016        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
3017        entry->mName = String8(componentName.c_str());
3018
3019        if (!OMXCodec::findCodecQuirks(
3020                    componentName.c_str(), &entry->mQuirks)) {
3021            entry->mQuirks = 0;
3022        }
3023    } else {
3024        CHECK(msg->findString("mime", &mime));
3025
3026        int32_t encoder;
3027        if (!msg->findInt32("encoder", &encoder)) {
3028            encoder = false;
3029        }
3030
3031        OMXCodec::findMatchingCodecs(
3032                mime.c_str(),
3033                encoder, // createEncoder
3034                NULL,  // matchComponentName
3035                0,     // flags
3036                &matchingCodecs);
3037    }
3038
3039    sp<CodecObserver> observer = new CodecObserver;
3040    IOMX::node_id node = NULL;
3041
3042    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
3043            ++matchIndex) {
3044        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
3045        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
3046
3047        pid_t tid = androidGetTid();
3048        int prevPriority = androidGetThreadPriority(tid);
3049        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
3050        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
3051        androidSetThreadPriority(tid, prevPriority);
3052
3053        if (err == OK) {
3054            break;
3055        }
3056
3057        node = NULL;
3058    }
3059
3060    if (node == NULL) {
3061        if (!mime.empty()) {
3062            ALOGE("Unable to instantiate a decoder for type '%s'.",
3063                 mime.c_str());
3064        } else {
3065            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
3066        }
3067
3068        mCodec->signalError(OMX_ErrorComponentNotFound);
3069        return false;
3070    }
3071
3072    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
3073    observer->setNotificationMessage(notify);
3074
3075    mCodec->mComponentName = componentName;
3076    mCodec->mFlags = 0;
3077
3078    if (componentName.endsWith(".secure")) {
3079        mCodec->mFlags |= kFlagIsSecure;
3080    }
3081
3082    mCodec->mQuirks = quirks;
3083    mCodec->mOMX = omx;
3084    mCodec->mNode = node;
3085
3086    mCodec->mPortEOS[kPortIndexInput] =
3087        mCodec->mPortEOS[kPortIndexOutput] = false;
3088
3089    mCodec->mInputEOSResult = OK;
3090
3091    {
3092        sp<AMessage> notify = mCodec->mNotify->dup();
3093        notify->setInt32("what", ACodec::kWhatComponentAllocated);
3094        notify->setString("componentName", mCodec->mComponentName.c_str());
3095        notify->post();
3096    }
3097
3098    mCodec->changeState(mCodec->mLoadedState);
3099
3100    return true;
3101}
3102
3103////////////////////////////////////////////////////////////////////////////////
3104
3105ACodec::LoadedState::LoadedState(ACodec *codec)
3106    : BaseState(codec) {
3107}
3108
3109void ACodec::LoadedState::stateEntered() {
3110    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
3111
3112    if (mCodec->mShutdownInProgress) {
3113        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
3114
3115        mCodec->mShutdownInProgress = false;
3116        mCodec->mKeepComponentAllocated = false;
3117
3118        onShutdown(keepComponentAllocated);
3119    }
3120}
3121
3122void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
3123    if (!keepComponentAllocated) {
3124        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
3125
3126        mCodec->mNativeWindow.clear();
3127        mCodec->mNode = NULL;
3128        mCodec->mOMX.clear();
3129        mCodec->mQuirks = 0;
3130        mCodec->mFlags = 0;
3131        mCodec->mComponentName.clear();
3132
3133        mCodec->changeState(mCodec->mUninitializedState);
3134    }
3135
3136    sp<AMessage> notify = mCodec->mNotify->dup();
3137    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3138    notify->post();
3139}
3140
3141bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
3142    bool handled = false;
3143
3144    switch (msg->what()) {
3145        case ACodec::kWhatConfigureComponent:
3146        {
3147            onConfigureComponent(msg);
3148            handled = true;
3149            break;
3150        }
3151
3152        case ACodec::kWhatStart:
3153        {
3154            onStart();
3155            handled = true;
3156            break;
3157        }
3158
3159        case ACodec::kWhatShutdown:
3160        {
3161            int32_t keepComponentAllocated;
3162            CHECK(msg->findInt32(
3163                        "keepComponentAllocated", &keepComponentAllocated));
3164
3165            onShutdown(keepComponentAllocated);
3166
3167            handled = true;
3168            break;
3169        }
3170
3171        case ACodec::kWhatFlush:
3172        {
3173            sp<AMessage> notify = mCodec->mNotify->dup();
3174            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3175            notify->post();
3176
3177            handled = true;
3178            break;
3179        }
3180
3181        default:
3182            return BaseState::onMessageReceived(msg);
3183    }
3184
3185    return handled;
3186}
3187
3188bool ACodec::LoadedState::onConfigureComponent(
3189        const sp<AMessage> &msg) {
3190    ALOGV("onConfigureComponent");
3191
3192    CHECK(mCodec->mNode != NULL);
3193
3194    AString mime;
3195    CHECK(msg->findString("mime", &mime));
3196
3197    status_t err = mCodec->configureCodec(mime.c_str(), msg);
3198
3199    if (err != OK) {
3200        ALOGE("[%s] configureCodec returning error %d",
3201              mCodec->mComponentName.c_str(), err);
3202
3203        mCodec->signalError(OMX_ErrorUndefined, err);
3204        return false;
3205    }
3206
3207    sp<RefBase> obj;
3208    if (msg->findObject("native-window", &obj)
3209            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
3210        sp<NativeWindowWrapper> nativeWindow(
3211                static_cast<NativeWindowWrapper *>(obj.get()));
3212        CHECK(nativeWindow != NULL);
3213        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
3214
3215        native_window_set_scaling_mode(
3216                mCodec->mNativeWindow.get(),
3217                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3218    }
3219    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
3220
3221    {
3222        sp<AMessage> notify = mCodec->mNotify->dup();
3223        notify->setInt32("what", ACodec::kWhatComponentConfigured);
3224        notify->post();
3225    }
3226
3227    return true;
3228}
3229
3230void ACodec::LoadedState::onStart() {
3231    ALOGV("onStart");
3232
3233    CHECK_EQ(mCodec->mOMX->sendCommand(
3234                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3235             (status_t)OK);
3236
3237    mCodec->changeState(mCodec->mLoadedToIdleState);
3238}
3239
3240////////////////////////////////////////////////////////////////////////////////
3241
3242ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
3243    : BaseState(codec) {
3244}
3245
3246void ACodec::LoadedToIdleState::stateEntered() {
3247    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
3248
3249    status_t err;
3250    if ((err = allocateBuffers()) != OK) {
3251        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
3252             "(error 0x%08x)",
3253             err);
3254
3255        mCodec->signalError(OMX_ErrorUndefined, err);
3256
3257        mCodec->changeState(mCodec->mLoadedState);
3258    }
3259}
3260
3261status_t ACodec::LoadedToIdleState::allocateBuffers() {
3262    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
3263
3264    if (err != OK) {
3265        return err;
3266    }
3267
3268    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
3269}
3270
3271bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3272    switch (msg->what()) {
3273        case kWhatShutdown:
3274        {
3275            mCodec->deferMessage(msg);
3276            return true;
3277        }
3278
3279        default:
3280            return BaseState::onMessageReceived(msg);
3281    }
3282}
3283
3284bool ACodec::LoadedToIdleState::onOMXEvent(
3285        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3286    switch (event) {
3287        case OMX_EventCmdComplete:
3288        {
3289            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3290            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3291
3292            CHECK_EQ(mCodec->mOMX->sendCommand(
3293                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
3294                     (status_t)OK);
3295
3296            mCodec->changeState(mCodec->mIdleToExecutingState);
3297
3298            return true;
3299        }
3300
3301        default:
3302            return BaseState::onOMXEvent(event, data1, data2);
3303    }
3304}
3305
3306////////////////////////////////////////////////////////////////////////////////
3307
3308ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
3309    : BaseState(codec) {
3310}
3311
3312void ACodec::IdleToExecutingState::stateEntered() {
3313    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
3314}
3315
3316bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3317    switch (msg->what()) {
3318        case kWhatShutdown:
3319        {
3320            mCodec->deferMessage(msg);
3321            return true;
3322        }
3323
3324        default:
3325            return BaseState::onMessageReceived(msg);
3326    }
3327}
3328
3329bool ACodec::IdleToExecutingState::onOMXEvent(
3330        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3331    switch (event) {
3332        case OMX_EventCmdComplete:
3333        {
3334            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3335            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
3336
3337            mCodec->mExecutingState->resume();
3338            mCodec->changeState(mCodec->mExecutingState);
3339
3340            return true;
3341        }
3342
3343        default:
3344            return BaseState::onOMXEvent(event, data1, data2);
3345    }
3346}
3347
3348////////////////////////////////////////////////////////////////////////////////
3349
3350ACodec::ExecutingState::ExecutingState(ACodec *codec)
3351    : BaseState(codec),
3352      mActive(false) {
3353}
3354
3355ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
3356        OMX_U32 portIndex) {
3357    return RESUBMIT_BUFFERS;
3358}
3359
3360void ACodec::ExecutingState::submitOutputBuffers() {
3361    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
3362        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
3363
3364        if (mCodec->mNativeWindow != NULL) {
3365            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
3366                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
3367
3368            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3369                continue;
3370            }
3371        } else {
3372            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3373        }
3374
3375        ALOGV("[%s] calling fillBuffer %p",
3376             mCodec->mComponentName.c_str(), info->mBufferID);
3377
3378        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3379                 (status_t)OK);
3380
3381        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3382    }
3383}
3384
3385void ACodec::ExecutingState::resume() {
3386    if (mActive) {
3387        ALOGV("[%s] We're already active, no need to resume.",
3388             mCodec->mComponentName.c_str());
3389
3390        return;
3391    }
3392
3393    submitOutputBuffers();
3394
3395    // Post the first input buffer.
3396    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
3397    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
3398
3399    postFillThisBuffer(info);
3400
3401    mActive = true;
3402}
3403
3404void ACodec::ExecutingState::stateEntered() {
3405    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
3406
3407    mCodec->processDeferredMessages();
3408}
3409
3410bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3411    bool handled = false;
3412
3413    switch (msg->what()) {
3414        case kWhatShutdown:
3415        {
3416            int32_t keepComponentAllocated;
3417            CHECK(msg->findInt32(
3418                        "keepComponentAllocated", &keepComponentAllocated));
3419
3420            mCodec->mShutdownInProgress = true;
3421            mCodec->mKeepComponentAllocated = keepComponentAllocated;
3422
3423            mActive = false;
3424
3425            CHECK_EQ(mCodec->mOMX->sendCommand(
3426                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3427                     (status_t)OK);
3428
3429            mCodec->changeState(mCodec->mExecutingToIdleState);
3430
3431            handled = true;
3432            break;
3433        }
3434
3435        case kWhatFlush:
3436        {
3437            ALOGV("[%s] ExecutingState flushing now "
3438                 "(codec owns %d/%d input, %d/%d output).",
3439                    mCodec->mComponentName.c_str(),
3440                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3441                    mCodec->mBuffers[kPortIndexInput].size(),
3442                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3443                    mCodec->mBuffers[kPortIndexOutput].size());
3444
3445            mActive = false;
3446
3447            CHECK_EQ(mCodec->mOMX->sendCommand(
3448                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3449                     (status_t)OK);
3450
3451            mCodec->changeState(mCodec->mFlushingState);
3452
3453            handled = true;
3454            break;
3455        }
3456
3457        case kWhatResume:
3458        {
3459            resume();
3460
3461            handled = true;
3462            break;
3463        }
3464
3465        case kWhatRequestIDRFrame:
3466        {
3467            status_t err = mCodec->requestIDRFrame();
3468            if (err != OK) {
3469                ALOGW("Requesting an IDR frame failed.");
3470            }
3471
3472            handled = true;
3473            break;
3474        }
3475
3476        default:
3477            handled = BaseState::onMessageReceived(msg);
3478            break;
3479    }
3480
3481    return handled;
3482}
3483
3484bool ACodec::ExecutingState::onOMXEvent(
3485        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3486    switch (event) {
3487        case OMX_EventPortSettingsChanged:
3488        {
3489            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3490
3491            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
3492                CHECK_EQ(mCodec->mOMX->sendCommand(
3493                            mCodec->mNode,
3494                            OMX_CommandPortDisable, kPortIndexOutput),
3495                         (status_t)OK);
3496
3497                mCodec->freeOutputBuffersNotOwnedByComponent();
3498
3499                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
3500            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3501                mCodec->mSentFormat = false;
3502            } else {
3503                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
3504                     mCodec->mComponentName.c_str(), data2);
3505            }
3506
3507            return true;
3508        }
3509
3510        case OMX_EventBufferFlag:
3511        {
3512            return true;
3513        }
3514
3515        default:
3516            return BaseState::onOMXEvent(event, data1, data2);
3517    }
3518}
3519
3520////////////////////////////////////////////////////////////////////////////////
3521
3522ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3523        ACodec *codec)
3524    : BaseState(codec) {
3525}
3526
3527ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3528        OMX_U32 portIndex) {
3529    if (portIndex == kPortIndexOutput) {
3530        return FREE_BUFFERS;
3531    }
3532
3533    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
3534
3535    return RESUBMIT_BUFFERS;
3536}
3537
3538bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
3539        const sp<AMessage> &msg) {
3540    bool handled = false;
3541
3542    switch (msg->what()) {
3543        case kWhatFlush:
3544        case kWhatShutdown:
3545        case kWhatResume:
3546        {
3547            if (msg->what() == kWhatResume) {
3548                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
3549            }
3550
3551            mCodec->deferMessage(msg);
3552            handled = true;
3553            break;
3554        }
3555
3556        default:
3557            handled = BaseState::onMessageReceived(msg);
3558            break;
3559    }
3560
3561    return handled;
3562}
3563
3564void ACodec::OutputPortSettingsChangedState::stateEntered() {
3565    ALOGV("[%s] Now handling output port settings change",
3566         mCodec->mComponentName.c_str());
3567}
3568
3569bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3570        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3571    switch (event) {
3572        case OMX_EventCmdComplete:
3573        {
3574            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3575                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3576
3577                ALOGV("[%s] Output port now disabled.",
3578                        mCodec->mComponentName.c_str());
3579
3580                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3581                mCodec->mDealer[kPortIndexOutput].clear();
3582
3583                CHECK_EQ(mCodec->mOMX->sendCommand(
3584                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3585                         (status_t)OK);
3586
3587                status_t err;
3588                if ((err = mCodec->allocateBuffersOnPort(
3589                                kPortIndexOutput)) != OK) {
3590                    ALOGE("Failed to allocate output port buffers after "
3591                         "port reconfiguration (error 0x%08x)",
3592                         err);
3593
3594                    mCodec->signalError(OMX_ErrorUndefined, err);
3595
3596                    // This is technically not correct, but appears to be
3597                    // the only way to free the component instance.
3598                    // Controlled transitioning from excecuting->idle
3599                    // and idle->loaded seem impossible probably because
3600                    // the output port never finishes re-enabling.
3601                    mCodec->mShutdownInProgress = true;
3602                    mCodec->mKeepComponentAllocated = false;
3603                    mCodec->changeState(mCodec->mLoadedState);
3604                }
3605
3606                return true;
3607            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3608                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3609
3610                mCodec->mSentFormat = false;
3611
3612                ALOGV("[%s] Output port now reenabled.",
3613                        mCodec->mComponentName.c_str());
3614
3615                if (mCodec->mExecutingState->active()) {
3616                    mCodec->mExecutingState->submitOutputBuffers();
3617                }
3618
3619                mCodec->changeState(mCodec->mExecutingState);
3620
3621                return true;
3622            }
3623
3624            return false;
3625        }
3626
3627        default:
3628            return false;
3629    }
3630}
3631
3632////////////////////////////////////////////////////////////////////////////////
3633
3634ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
3635    : BaseState(codec),
3636      mComponentNowIdle(false) {
3637}
3638
3639bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3640    bool handled = false;
3641
3642    switch (msg->what()) {
3643        case kWhatFlush:
3644        {
3645            // Don't send me a flush request if you previously wanted me
3646            // to shutdown.
3647            TRESPASS();
3648            break;
3649        }
3650
3651        case kWhatShutdown:
3652        {
3653            // We're already doing that...
3654
3655            handled = true;
3656            break;
3657        }
3658
3659        default:
3660            handled = BaseState::onMessageReceived(msg);
3661            break;
3662    }
3663
3664    return handled;
3665}
3666
3667void ACodec::ExecutingToIdleState::stateEntered() {
3668    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
3669
3670    mComponentNowIdle = false;
3671    mCodec->mSentFormat = false;
3672}
3673
3674bool ACodec::ExecutingToIdleState::onOMXEvent(
3675        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3676    switch (event) {
3677        case OMX_EventCmdComplete:
3678        {
3679            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3680            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3681
3682            mComponentNowIdle = true;
3683
3684            changeStateIfWeOwnAllBuffers();
3685
3686            return true;
3687        }
3688
3689        case OMX_EventPortSettingsChanged:
3690        case OMX_EventBufferFlag:
3691        {
3692            // We're shutting down and don't care about this anymore.
3693            return true;
3694        }
3695
3696        default:
3697            return BaseState::onOMXEvent(event, data1, data2);
3698    }
3699}
3700
3701void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
3702    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
3703        CHECK_EQ(mCodec->mOMX->sendCommand(
3704                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3705                 (status_t)OK);
3706
3707        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3708        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3709
3710        if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) {
3711            // We push enough 1x1 blank buffers to ensure that one of
3712            // them has made it to the display.  This allows the OMX
3713            // component teardown to zero out any protected buffers
3714            // without the risk of scanning out one of those buffers.
3715            mCodec->pushBlankBuffersToNativeWindow();
3716        }
3717
3718        mCodec->changeState(mCodec->mIdleToLoadedState);
3719    }
3720}
3721
3722void ACodec::ExecutingToIdleState::onInputBufferFilled(
3723        const sp<AMessage> &msg) {
3724    BaseState::onInputBufferFilled(msg);
3725
3726    changeStateIfWeOwnAllBuffers();
3727}
3728
3729void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3730        const sp<AMessage> &msg) {
3731    BaseState::onOutputBufferDrained(msg);
3732
3733    changeStateIfWeOwnAllBuffers();
3734}
3735
3736////////////////////////////////////////////////////////////////////////////////
3737
3738ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3739    : BaseState(codec) {
3740}
3741
3742bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3743    bool handled = false;
3744
3745    switch (msg->what()) {
3746        case kWhatShutdown:
3747        {
3748            // We're already doing that...
3749
3750            handled = true;
3751            break;
3752        }
3753
3754        case kWhatFlush:
3755        {
3756            // Don't send me a flush request if you previously wanted me
3757            // to shutdown.
3758            TRESPASS();
3759            break;
3760        }
3761
3762        default:
3763            handled = BaseState::onMessageReceived(msg);
3764            break;
3765    }
3766
3767    return handled;
3768}
3769
3770void ACodec::IdleToLoadedState::stateEntered() {
3771    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
3772}
3773
3774bool ACodec::IdleToLoadedState::onOMXEvent(
3775        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3776    switch (event) {
3777        case OMX_EventCmdComplete:
3778        {
3779            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3780            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3781
3782            mCodec->changeState(mCodec->mLoadedState);
3783
3784            return true;
3785        }
3786
3787        default:
3788            return BaseState::onOMXEvent(event, data1, data2);
3789    }
3790}
3791
3792////////////////////////////////////////////////////////////////////////////////
3793
3794ACodec::FlushingState::FlushingState(ACodec *codec)
3795    : BaseState(codec) {
3796}
3797
3798void ACodec::FlushingState::stateEntered() {
3799    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
3800
3801    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3802}
3803
3804bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3805    bool handled = false;
3806
3807    switch (msg->what()) {
3808        case kWhatShutdown:
3809        {
3810            mCodec->deferMessage(msg);
3811            break;
3812        }
3813
3814        case kWhatFlush:
3815        {
3816            // We're already doing this right now.
3817            handled = true;
3818            break;
3819        }
3820
3821        default:
3822            handled = BaseState::onMessageReceived(msg);
3823            break;
3824    }
3825
3826    return handled;
3827}
3828
3829bool ACodec::FlushingState::onOMXEvent(
3830        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3831    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
3832            mCodec->mComponentName.c_str(), event, data1);
3833
3834    switch (event) {
3835        case OMX_EventCmdComplete:
3836        {
3837            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3838
3839            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3840                CHECK(!mFlushComplete[data2]);
3841                mFlushComplete[data2] = true;
3842
3843                if (mFlushComplete[kPortIndexInput]
3844                        && mFlushComplete[kPortIndexOutput]) {
3845                    changeStateIfWeOwnAllBuffers();
3846                }
3847            } else {
3848                CHECK_EQ(data2, OMX_ALL);
3849                CHECK(mFlushComplete[kPortIndexInput]);
3850                CHECK(mFlushComplete[kPortIndexOutput]);
3851
3852                changeStateIfWeOwnAllBuffers();
3853            }
3854
3855            return true;
3856        }
3857
3858        case OMX_EventPortSettingsChanged:
3859        {
3860            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3861            msg->setInt32("type", omx_message::EVENT);
3862            msg->setPointer("node", mCodec->mNode);
3863            msg->setInt32("event", event);
3864            msg->setInt32("data1", data1);
3865            msg->setInt32("data2", data2);
3866
3867            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
3868                 mCodec->mComponentName.c_str());
3869
3870            mCodec->deferMessage(msg);
3871
3872            return true;
3873        }
3874
3875        default:
3876            return BaseState::onOMXEvent(event, data1, data2);
3877    }
3878
3879    return true;
3880}
3881
3882void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3883    BaseState::onOutputBufferDrained(msg);
3884
3885    changeStateIfWeOwnAllBuffers();
3886}
3887
3888void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3889    BaseState::onInputBufferFilled(msg);
3890
3891    changeStateIfWeOwnAllBuffers();
3892}
3893
3894void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3895    if (mFlushComplete[kPortIndexInput]
3896            && mFlushComplete[kPortIndexOutput]
3897            && mCodec->allYourBuffersAreBelongToUs()) {
3898        sp<AMessage> notify = mCodec->mNotify->dup();
3899        notify->setInt32("what", ACodec::kWhatFlushCompleted);
3900        notify->post();
3901
3902        mCodec->mPortEOS[kPortIndexInput] =
3903            mCodec->mPortEOS[kPortIndexOutput] = false;
3904
3905        mCodec->mInputEOSResult = OK;
3906
3907        mCodec->changeState(mCodec->mExecutingState);
3908    }
3909}
3910
3911}  // namespace android
3912