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