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