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