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