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