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