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