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