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