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