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