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