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