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