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