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