ACodec.cpp revision d725d23ae67045c22003d419d5c31ca1d551da89
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        case OMX_VIDEO_CodingVP8:
1966        case OMX_VIDEO_CodingVP9:
1967            err = setupVPXEncoderParameters(msg);
1968            break;
1969
1970        default:
1971            break;
1972    }
1973
1974    ALOGI("setupVideoEncoder succeeded");
1975
1976    return err;
1977}
1978
1979status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
1980    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
1981    InitOMXParams(&params);
1982    params.nPortIndex = kPortIndexOutput;
1983
1984    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
1985
1986    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
1987            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
1988        int32_t mbs;
1989        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
1990            return INVALID_OPERATION;
1991        }
1992        params.nCirMBs = mbs;
1993    }
1994
1995    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
1996            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
1997        int32_t mbs;
1998        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
1999            return INVALID_OPERATION;
2000        }
2001        params.nAirMBs = mbs;
2002
2003        int32_t ref;
2004        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2005            return INVALID_OPERATION;
2006        }
2007        params.nAirRef = ref;
2008    }
2009
2010    status_t err = mOMX->setParameter(
2011            mNode, OMX_IndexParamVideoIntraRefresh,
2012            &params, sizeof(params));
2013    return err;
2014}
2015
2016static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2017    if (iFramesInterval < 0) {
2018        return 0xFFFFFFFF;
2019    } else if (iFramesInterval == 0) {
2020        return 0;
2021    }
2022    OMX_U32 ret = frameRate * iFramesInterval;
2023    CHECK(ret > 1);
2024    return ret;
2025}
2026
2027static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2028    int32_t tmp;
2029    if (!msg->findInt32("bitrate-mode", &tmp)) {
2030        return OMX_Video_ControlRateVariable;
2031    }
2032
2033    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2034}
2035
2036status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2037    int32_t bitrate, iFrameInterval;
2038    if (!msg->findInt32("bitrate", &bitrate)
2039            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2040        return INVALID_OPERATION;
2041    }
2042
2043    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2044
2045    float frameRate;
2046    if (!msg->findFloat("frame-rate", &frameRate)) {
2047        int32_t tmp;
2048        if (!msg->findInt32("frame-rate", &tmp)) {
2049            return INVALID_OPERATION;
2050        }
2051        frameRate = (float)tmp;
2052    }
2053
2054    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2055    InitOMXParams(&mpeg4type);
2056    mpeg4type.nPortIndex = kPortIndexOutput;
2057
2058    status_t err = mOMX->getParameter(
2059            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2060
2061    if (err != OK) {
2062        return err;
2063    }
2064
2065    mpeg4type.nSliceHeaderSpacing = 0;
2066    mpeg4type.bSVH = OMX_FALSE;
2067    mpeg4type.bGov = OMX_FALSE;
2068
2069    mpeg4type.nAllowedPictureTypes =
2070        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2071
2072    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2073    if (mpeg4type.nPFrames == 0) {
2074        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2075    }
2076    mpeg4type.nBFrames = 0;
2077    mpeg4type.nIDCVLCThreshold = 0;
2078    mpeg4type.bACPred = OMX_TRUE;
2079    mpeg4type.nMaxPacketSize = 256;
2080    mpeg4type.nTimeIncRes = 1000;
2081    mpeg4type.nHeaderExtension = 0;
2082    mpeg4type.bReversibleVLC = OMX_FALSE;
2083
2084    int32_t profile;
2085    if (msg->findInt32("profile", &profile)) {
2086        int32_t level;
2087        if (!msg->findInt32("level", &level)) {
2088            return INVALID_OPERATION;
2089        }
2090
2091        err = verifySupportForProfileAndLevel(profile, level);
2092
2093        if (err != OK) {
2094            return err;
2095        }
2096
2097        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2098        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2099    }
2100
2101    err = mOMX->setParameter(
2102            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2103
2104    if (err != OK) {
2105        return err;
2106    }
2107
2108    err = configureBitrate(bitrate, bitrateMode);
2109
2110    if (err != OK) {
2111        return err;
2112    }
2113
2114    return setupErrorCorrectionParameters();
2115}
2116
2117status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2118    int32_t bitrate, iFrameInterval;
2119    if (!msg->findInt32("bitrate", &bitrate)
2120            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2121        return INVALID_OPERATION;
2122    }
2123
2124    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2125
2126    float frameRate;
2127    if (!msg->findFloat("frame-rate", &frameRate)) {
2128        int32_t tmp;
2129        if (!msg->findInt32("frame-rate", &tmp)) {
2130            return INVALID_OPERATION;
2131        }
2132        frameRate = (float)tmp;
2133    }
2134
2135    OMX_VIDEO_PARAM_H263TYPE h263type;
2136    InitOMXParams(&h263type);
2137    h263type.nPortIndex = kPortIndexOutput;
2138
2139    status_t err = mOMX->getParameter(
2140            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2141
2142    if (err != OK) {
2143        return err;
2144    }
2145
2146    h263type.nAllowedPictureTypes =
2147        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2148
2149    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2150    if (h263type.nPFrames == 0) {
2151        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2152    }
2153    h263type.nBFrames = 0;
2154
2155    int32_t profile;
2156    if (msg->findInt32("profile", &profile)) {
2157        int32_t level;
2158        if (!msg->findInt32("level", &level)) {
2159            return INVALID_OPERATION;
2160        }
2161
2162        err = verifySupportForProfileAndLevel(profile, level);
2163
2164        if (err != OK) {
2165            return err;
2166        }
2167
2168        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2169        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2170    }
2171
2172    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2173    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2174    h263type.nPictureHeaderRepetition = 0;
2175    h263type.nGOBHeaderInterval = 0;
2176
2177    err = mOMX->setParameter(
2178            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2179
2180    if (err != OK) {
2181        return err;
2182    }
2183
2184    err = configureBitrate(bitrate, bitrateMode);
2185
2186    if (err != OK) {
2187        return err;
2188    }
2189
2190    return setupErrorCorrectionParameters();
2191}
2192
2193status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2194    int32_t bitrate, iFrameInterval;
2195    if (!msg->findInt32("bitrate", &bitrate)
2196            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2197        return INVALID_OPERATION;
2198    }
2199
2200    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2201
2202    float frameRate;
2203    if (!msg->findFloat("frame-rate", &frameRate)) {
2204        int32_t tmp;
2205        if (!msg->findInt32("frame-rate", &tmp)) {
2206            return INVALID_OPERATION;
2207        }
2208        frameRate = (float)tmp;
2209    }
2210
2211    status_t err = OK;
2212    int32_t intraRefreshMode = 0;
2213    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2214        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2215        if (err != OK) {
2216            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2217                    err, intraRefreshMode);
2218            return err;
2219        }
2220    }
2221
2222    OMX_VIDEO_PARAM_AVCTYPE h264type;
2223    InitOMXParams(&h264type);
2224    h264type.nPortIndex = kPortIndexOutput;
2225
2226    err = mOMX->getParameter(
2227            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2228
2229    if (err != OK) {
2230        return err;
2231    }
2232
2233    h264type.nAllowedPictureTypes =
2234        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2235
2236    int32_t profile;
2237    if (msg->findInt32("profile", &profile)) {
2238        int32_t level;
2239        if (!msg->findInt32("level", &level)) {
2240            return INVALID_OPERATION;
2241        }
2242
2243        err = verifySupportForProfileAndLevel(profile, level);
2244
2245        if (err != OK) {
2246            return err;
2247        }
2248
2249        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2250        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2251    }
2252
2253    // XXX
2254    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2255        ALOGW("Use baseline profile instead of %d for AVC recording",
2256            h264type.eProfile);
2257        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2258    }
2259
2260    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2261        h264type.nSliceHeaderSpacing = 0;
2262        h264type.bUseHadamard = OMX_TRUE;
2263        h264type.nRefFrames = 1;
2264        h264type.nBFrames = 0;
2265        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2266        if (h264type.nPFrames == 0) {
2267            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2268        }
2269        h264type.nRefIdx10ActiveMinus1 = 0;
2270        h264type.nRefIdx11ActiveMinus1 = 0;
2271        h264type.bEntropyCodingCABAC = OMX_FALSE;
2272        h264type.bWeightedPPrediction = OMX_FALSE;
2273        h264type.bconstIpred = OMX_FALSE;
2274        h264type.bDirect8x8Inference = OMX_FALSE;
2275        h264type.bDirectSpatialTemporal = OMX_FALSE;
2276        h264type.nCabacInitIdc = 0;
2277    }
2278
2279    if (h264type.nBFrames != 0) {
2280        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2281    }
2282
2283    h264type.bEnableUEP = OMX_FALSE;
2284    h264type.bEnableFMO = OMX_FALSE;
2285    h264type.bEnableASO = OMX_FALSE;
2286    h264type.bEnableRS = OMX_FALSE;
2287    h264type.bFrameMBsOnly = OMX_TRUE;
2288    h264type.bMBAFF = OMX_FALSE;
2289    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2290
2291    err = mOMX->setParameter(
2292            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2293
2294    if (err != OK) {
2295        return err;
2296    }
2297
2298    return configureBitrate(bitrate, bitrateMode);
2299}
2300
2301status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2302    int32_t bitrate;
2303    if (!msg->findInt32("bitrate", &bitrate)) {
2304        return INVALID_OPERATION;
2305    }
2306
2307    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2308
2309    return configureBitrate(bitrate, bitrateMode);
2310}
2311
2312status_t ACodec::verifySupportForProfileAndLevel(
2313        int32_t profile, int32_t level) {
2314    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2315    InitOMXParams(&params);
2316    params.nPortIndex = kPortIndexOutput;
2317
2318    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2319        status_t err = mOMX->getParameter(
2320                mNode,
2321                OMX_IndexParamVideoProfileLevelQuerySupported,
2322                &params,
2323                sizeof(params));
2324
2325        if (err != OK) {
2326            return err;
2327        }
2328
2329        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
2330        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
2331
2332        if (profile == supportedProfile && level <= supportedLevel) {
2333            return OK;
2334        }
2335    }
2336}
2337
2338status_t ACodec::configureBitrate(
2339        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
2340    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
2341    InitOMXParams(&bitrateType);
2342    bitrateType.nPortIndex = kPortIndexOutput;
2343
2344    status_t err = mOMX->getParameter(
2345            mNode, OMX_IndexParamVideoBitrate,
2346            &bitrateType, sizeof(bitrateType));
2347
2348    if (err != OK) {
2349        return err;
2350    }
2351
2352    bitrateType.eControlRate = bitrateMode;
2353    bitrateType.nTargetBitrate = bitrate;
2354
2355    return mOMX->setParameter(
2356            mNode, OMX_IndexParamVideoBitrate,
2357            &bitrateType, sizeof(bitrateType));
2358}
2359
2360status_t ACodec::setupErrorCorrectionParameters() {
2361    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
2362    InitOMXParams(&errorCorrectionType);
2363    errorCorrectionType.nPortIndex = kPortIndexOutput;
2364
2365    status_t err = mOMX->getParameter(
2366            mNode, OMX_IndexParamVideoErrorCorrection,
2367            &errorCorrectionType, sizeof(errorCorrectionType));
2368
2369    if (err != OK) {
2370        return OK;  // Optional feature. Ignore this failure
2371    }
2372
2373    errorCorrectionType.bEnableHEC = OMX_FALSE;
2374    errorCorrectionType.bEnableResync = OMX_TRUE;
2375    errorCorrectionType.nResynchMarkerSpacing = 256;
2376    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
2377    errorCorrectionType.bEnableRVLC = OMX_FALSE;
2378
2379    return mOMX->setParameter(
2380            mNode, OMX_IndexParamVideoErrorCorrection,
2381            &errorCorrectionType, sizeof(errorCorrectionType));
2382}
2383
2384status_t ACodec::setVideoFormatOnPort(
2385        OMX_U32 portIndex,
2386        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
2387    OMX_PARAM_PORTDEFINITIONTYPE def;
2388    InitOMXParams(&def);
2389    def.nPortIndex = portIndex;
2390
2391    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2392
2393    status_t err = mOMX->getParameter(
2394            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2395
2396    CHECK_EQ(err, (status_t)OK);
2397
2398    if (portIndex == kPortIndexInput) {
2399        // XXX Need a (much) better heuristic to compute input buffer sizes.
2400        const size_t X = 64 * 1024;
2401        if (def.nBufferSize < X) {
2402            def.nBufferSize = X;
2403        }
2404    }
2405
2406    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
2407
2408    video_def->nFrameWidth = width;
2409    video_def->nFrameHeight = height;
2410
2411    if (portIndex == kPortIndexInput) {
2412        video_def->eCompressionFormat = compressionFormat;
2413        video_def->eColorFormat = OMX_COLOR_FormatUnused;
2414    }
2415
2416    err = mOMX->setParameter(
2417            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2418
2419    return err;
2420}
2421
2422status_t ACodec::initNativeWindow() {
2423    if (mNativeWindow != NULL) {
2424        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
2425    }
2426
2427    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
2428    return OK;
2429}
2430
2431size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
2432    size_t n = 0;
2433
2434    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2435        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
2436
2437        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
2438            ++n;
2439        }
2440    }
2441
2442    return n;
2443}
2444
2445size_t ACodec::countBuffersOwnedByNativeWindow() const {
2446    size_t n = 0;
2447
2448    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
2449        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
2450
2451        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2452            ++n;
2453        }
2454    }
2455
2456    return n;
2457}
2458
2459void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
2460    if (mNativeWindow == NULL) {
2461        return;
2462    }
2463
2464    int minUndequeuedBufs = 0;
2465    status_t err = mNativeWindow->query(
2466            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
2467            &minUndequeuedBufs);
2468
2469    if (err != OK) {
2470        ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
2471                mComponentName.c_str(), strerror(-err), -err);
2472
2473        minUndequeuedBufs = 0;
2474    }
2475
2476    while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs
2477            && dequeueBufferFromNativeWindow() != NULL) {
2478        // these buffers will be submitted as regular buffers; account for this
2479        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
2480            --mMetaDataBuffersToSubmit;
2481        }
2482    }
2483}
2484
2485bool ACodec::allYourBuffersAreBelongToUs(
2486        OMX_U32 portIndex) {
2487    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2488        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
2489
2490        if (info->mStatus != BufferInfo::OWNED_BY_US
2491                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2492            ALOGV("[%s] Buffer %p on port %ld still has status %d",
2493                    mComponentName.c_str(),
2494                    info->mBufferID, portIndex, info->mStatus);
2495            return false;
2496        }
2497    }
2498
2499    return true;
2500}
2501
2502bool ACodec::allYourBuffersAreBelongToUs() {
2503    return allYourBuffersAreBelongToUs(kPortIndexInput)
2504        && allYourBuffersAreBelongToUs(kPortIndexOutput);
2505}
2506
2507void ACodec::deferMessage(const sp<AMessage> &msg) {
2508    bool wasEmptyBefore = mDeferredQueue.empty();
2509    mDeferredQueue.push_back(msg);
2510}
2511
2512void ACodec::processDeferredMessages() {
2513    List<sp<AMessage> > queue = mDeferredQueue;
2514    mDeferredQueue.clear();
2515
2516    List<sp<AMessage> >::iterator it = queue.begin();
2517    while (it != queue.end()) {
2518        onMessageReceived(*it++);
2519    }
2520}
2521
2522void ACodec::sendFormatChange(const sp<AMessage> &reply) {
2523    sp<AMessage> notify = mNotify->dup();
2524    notify->setInt32("what", kWhatOutputFormatChanged);
2525
2526    OMX_PARAM_PORTDEFINITIONTYPE def;
2527    InitOMXParams(&def);
2528    def.nPortIndex = kPortIndexOutput;
2529
2530    CHECK_EQ(mOMX->getParameter(
2531                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
2532             (status_t)OK);
2533
2534    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
2535
2536    switch (def.eDomain) {
2537        case OMX_PortDomainVideo:
2538        {
2539            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2540
2541            AString mime;
2542            if (!mIsEncoder) {
2543                notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
2544            } else if (GetMimeTypeForVideoCoding(
2545                        videoDef->eCompressionFormat, &mime) != OK) {
2546                notify->setString("mime", "application/octet-stream");
2547            } else {
2548                notify->setString("mime", mime.c_str());
2549            }
2550
2551            notify->setInt32("width", videoDef->nFrameWidth);
2552            notify->setInt32("height", videoDef->nFrameHeight);
2553
2554            if (!mIsEncoder) {
2555                notify->setInt32("stride", videoDef->nStride);
2556                notify->setInt32("slice-height", videoDef->nSliceHeight);
2557                notify->setInt32("color-format", videoDef->eColorFormat);
2558
2559                OMX_CONFIG_RECTTYPE rect;
2560                InitOMXParams(&rect);
2561                rect.nPortIndex = kPortIndexOutput;
2562
2563                if (mOMX->getConfig(
2564                            mNode, OMX_IndexConfigCommonOutputCrop,
2565                            &rect, sizeof(rect)) != OK) {
2566                    rect.nLeft = 0;
2567                    rect.nTop = 0;
2568                    rect.nWidth = videoDef->nFrameWidth;
2569                    rect.nHeight = videoDef->nFrameHeight;
2570                }
2571
2572                CHECK_GE(rect.nLeft, 0);
2573                CHECK_GE(rect.nTop, 0);
2574                CHECK_GE(rect.nWidth, 0u);
2575                CHECK_GE(rect.nHeight, 0u);
2576                CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
2577                CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
2578
2579                notify->setRect(
2580                        "crop",
2581                        rect.nLeft,
2582                        rect.nTop,
2583                        rect.nLeft + rect.nWidth - 1,
2584                        rect.nTop + rect.nHeight - 1);
2585
2586                if (mNativeWindow != NULL) {
2587                    reply->setRect(
2588                            "crop",
2589                            rect.nLeft,
2590                            rect.nTop,
2591                            rect.nLeft + rect.nWidth,
2592                            rect.nTop + rect.nHeight);
2593                }
2594            }
2595            break;
2596        }
2597
2598        case OMX_PortDomainAudio:
2599        {
2600            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2601
2602            switch ((int)audioDef->eEncoding) {
2603                case OMX_AUDIO_CodingPCM:
2604                {
2605                    OMX_AUDIO_PARAM_PCMMODETYPE params;
2606                    InitOMXParams(&params);
2607                    params.nPortIndex = kPortIndexOutput;
2608
2609                    CHECK_EQ(mOMX->getParameter(
2610                                mNode, OMX_IndexParamAudioPcm,
2611                                &params, sizeof(params)),
2612                             (status_t)OK);
2613
2614                    CHECK_GT(params.nChannels, 0);
2615                    CHECK(params.nChannels == 1 || params.bInterleaved);
2616                    CHECK_EQ(params.nBitPerSample, 16u);
2617
2618                    CHECK_EQ((int)params.eNumData,
2619                             (int)OMX_NumericalDataSigned);
2620
2621                    CHECK_EQ((int)params.ePCMMode,
2622                             (int)OMX_AUDIO_PCMModeLinear);
2623
2624                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2625                    notify->setInt32("channel-count", params.nChannels);
2626                    notify->setInt32("sample-rate", params.nSamplingRate);
2627                    if (mEncoderDelay + mEncoderPadding) {
2628                        size_t frameSize = params.nChannels * sizeof(int16_t);
2629                        if (mSkipCutBuffer != NULL) {
2630                            size_t prevbufsize = mSkipCutBuffer->size();
2631                            if (prevbufsize != 0) {
2632                                ALOGW("Replacing SkipCutBuffer holding %d "
2633                                      "bytes",
2634                                      prevbufsize);
2635                            }
2636                        }
2637                        mSkipCutBuffer = new SkipCutBuffer(
2638                                mEncoderDelay * frameSize,
2639                                mEncoderPadding * frameSize);
2640                    }
2641
2642                    if (mChannelMaskPresent) {
2643                        notify->setInt32("channel-mask", mChannelMask);
2644                    }
2645                    break;
2646                }
2647
2648                case OMX_AUDIO_CodingAAC:
2649                {
2650                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
2651                    InitOMXParams(&params);
2652                    params.nPortIndex = kPortIndexOutput;
2653
2654                    CHECK_EQ(mOMX->getParameter(
2655                                mNode, OMX_IndexParamAudioAac,
2656                                &params, sizeof(params)),
2657                             (status_t)OK);
2658
2659                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
2660                    notify->setInt32("channel-count", params.nChannels);
2661                    notify->setInt32("sample-rate", params.nSampleRate);
2662                    break;
2663                }
2664
2665                case OMX_AUDIO_CodingAMR:
2666                {
2667                    OMX_AUDIO_PARAM_AMRTYPE params;
2668                    InitOMXParams(&params);
2669                    params.nPortIndex = kPortIndexOutput;
2670
2671                    CHECK_EQ(mOMX->getParameter(
2672                                mNode, OMX_IndexParamAudioAmr,
2673                                &params, sizeof(params)),
2674                             (status_t)OK);
2675
2676                    notify->setInt32("channel-count", 1);
2677                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
2678                        notify->setString(
2679                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
2680
2681                        notify->setInt32("sample-rate", 16000);
2682                    } else {
2683                        notify->setString(
2684                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
2685
2686                        notify->setInt32("sample-rate", 8000);
2687                    }
2688                    break;
2689                }
2690
2691                case OMX_AUDIO_CodingFLAC:
2692                {
2693                    OMX_AUDIO_PARAM_FLACTYPE params;
2694                    InitOMXParams(&params);
2695                    params.nPortIndex = kPortIndexOutput;
2696
2697                    CHECK_EQ(mOMX->getParameter(
2698                                mNode, OMX_IndexParamAudioFlac,
2699                                &params, sizeof(params)),
2700                             (status_t)OK);
2701
2702                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
2703                    notify->setInt32("channel-count", params.nChannels);
2704                    notify->setInt32("sample-rate", params.nSampleRate);
2705                    break;
2706                }
2707
2708                case OMX_AUDIO_CodingAndroidAC3:
2709                {
2710                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
2711                    InitOMXParams(&params);
2712                    params.nPortIndex = kPortIndexOutput;
2713
2714                    CHECK_EQ((status_t)OK, mOMX->getParameter(
2715                            mNode,
2716                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2717                            &params,
2718                            sizeof(params)));
2719
2720                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
2721                    notify->setInt32("channel-count", params.nChannels);
2722                    notify->setInt32("sample-rate", params.nSampleRate);
2723                    break;
2724                }
2725
2726                default:
2727                    TRESPASS();
2728            }
2729            break;
2730        }
2731
2732        default:
2733            TRESPASS();
2734    }
2735
2736    notify->post();
2737
2738    mSentFormat = true;
2739}
2740
2741void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2742    sp<AMessage> notify = mNotify->dup();
2743    notify->setInt32("what", ACodec::kWhatError);
2744    notify->setInt32("omx-error", error);
2745    notify->setInt32("err", internalError);
2746    notify->post();
2747}
2748
2749status_t ACodec::pushBlankBuffersToNativeWindow() {
2750    status_t err = NO_ERROR;
2751    ANativeWindowBuffer* anb = NULL;
2752    int numBufs = 0;
2753    int minUndequeuedBufs = 0;
2754
2755    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2756    // no frames get dropped by SurfaceFlinger assuming that these are video
2757    // frames.
2758    err = native_window_api_disconnect(mNativeWindow.get(),
2759            NATIVE_WINDOW_API_MEDIA);
2760    if (err != NO_ERROR) {
2761        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2762                strerror(-err), -err);
2763        return err;
2764    }
2765
2766    err = native_window_api_connect(mNativeWindow.get(),
2767            NATIVE_WINDOW_API_CPU);
2768    if (err != NO_ERROR) {
2769        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2770                strerror(-err), -err);
2771        return err;
2772    }
2773
2774    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2775            HAL_PIXEL_FORMAT_RGBX_8888);
2776    if (err != NO_ERROR) {
2777        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2778                strerror(-err), -err);
2779        goto error;
2780    }
2781
2782    err = native_window_set_scaling_mode(mNativeWindow.get(),
2783                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
2784    if (err != NO_ERROR) {
2785        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
2786              strerror(-err), -err);
2787        goto error;
2788    }
2789
2790    err = native_window_set_usage(mNativeWindow.get(),
2791            GRALLOC_USAGE_SW_WRITE_OFTEN);
2792    if (err != NO_ERROR) {
2793        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
2794                strerror(-err), -err);
2795        goto error;
2796    }
2797
2798    err = mNativeWindow->query(mNativeWindow.get(),
2799            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2800    if (err != NO_ERROR) {
2801        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2802                "failed: %s (%d)", strerror(-err), -err);
2803        goto error;
2804    }
2805
2806    numBufs = minUndequeuedBufs + 1;
2807    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2808    if (err != NO_ERROR) {
2809        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2810                strerror(-err), -err);
2811        goto error;
2812    }
2813
2814    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
2815    // buffer twice.  This should guarantee that the buffer has been displayed
2816    // on the screen and then been replaced, so an previous video frames are
2817    // guaranteed NOT to be currently displayed.
2818    for (int i = 0; i < numBufs + 1; i++) {
2819        int fenceFd = -1;
2820        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
2821        if (err != NO_ERROR) {
2822            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2823                    strerror(-err), -err);
2824            goto error;
2825        }
2826
2827        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2828
2829        // Fill the buffer with the a 1x1 checkerboard pattern ;)
2830        uint32_t* img = NULL;
2831        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2832        if (err != NO_ERROR) {
2833            ALOGE("error pushing blank frames: lock failed: %s (%d)",
2834                    strerror(-err), -err);
2835            goto error;
2836        }
2837
2838        *img = 0;
2839
2840        err = buf->unlock();
2841        if (err != NO_ERROR) {
2842            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
2843                    strerror(-err), -err);
2844            goto error;
2845        }
2846
2847        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2848                buf->getNativeBuffer(), -1);
2849        if (err != NO_ERROR) {
2850            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2851                    strerror(-err), -err);
2852            goto error;
2853        }
2854
2855        anb = NULL;
2856    }
2857
2858error:
2859
2860    if (err != NO_ERROR) {
2861        // Clean up after an error.
2862        if (anb != NULL) {
2863            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
2864        }
2865
2866        native_window_api_disconnect(mNativeWindow.get(),
2867                NATIVE_WINDOW_API_CPU);
2868        native_window_api_connect(mNativeWindow.get(),
2869                NATIVE_WINDOW_API_MEDIA);
2870
2871        return err;
2872    } else {
2873        // Clean up after success.
2874        err = native_window_api_disconnect(mNativeWindow.get(),
2875                NATIVE_WINDOW_API_CPU);
2876        if (err != NO_ERROR) {
2877            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2878                    strerror(-err), -err);
2879            return err;
2880        }
2881
2882        err = native_window_api_connect(mNativeWindow.get(),
2883                NATIVE_WINDOW_API_MEDIA);
2884        if (err != NO_ERROR) {
2885            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2886                    strerror(-err), -err);
2887            return err;
2888        }
2889
2890        return NO_ERROR;
2891    }
2892}
2893
2894////////////////////////////////////////////////////////////////////////////////
2895
2896ACodec::PortDescription::PortDescription() {
2897}
2898
2899status_t ACodec::requestIDRFrame() {
2900    if (!mIsEncoder) {
2901        return ERROR_UNSUPPORTED;
2902    }
2903
2904    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
2905    InitOMXParams(&params);
2906
2907    params.nPortIndex = kPortIndexOutput;
2908    params.IntraRefreshVOP = OMX_TRUE;
2909
2910    return mOMX->setConfig(
2911            mNode,
2912            OMX_IndexConfigVideoIntraVOPRefresh,
2913            &params,
2914            sizeof(params));
2915}
2916
2917void ACodec::PortDescription::addBuffer(
2918        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
2919    mBufferIDs.push_back(id);
2920    mBuffers.push_back(buffer);
2921}
2922
2923size_t ACodec::PortDescription::countBuffers() {
2924    return mBufferIDs.size();
2925}
2926
2927IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
2928    return mBufferIDs.itemAt(index);
2929}
2930
2931sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
2932    return mBuffers.itemAt(index);
2933}
2934
2935////////////////////////////////////////////////////////////////////////////////
2936
2937ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2938    : AState(parentState),
2939      mCodec(codec) {
2940}
2941
2942ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2943    return KEEP_BUFFERS;
2944}
2945
2946bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2947    switch (msg->what()) {
2948        case kWhatInputBufferFilled:
2949        {
2950            onInputBufferFilled(msg);
2951            break;
2952        }
2953
2954        case kWhatOutputBufferDrained:
2955        {
2956            onOutputBufferDrained(msg);
2957            break;
2958        }
2959
2960        case ACodec::kWhatOMXMessage:
2961        {
2962            return onOMXMessage(msg);
2963        }
2964
2965        case ACodec::kWhatCreateInputSurface:
2966        case ACodec::kWhatSignalEndOfInputStream:
2967        {
2968            ALOGE("Message 0x%x was not handled", msg->what());
2969            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
2970            return true;
2971        }
2972
2973        case ACodec::kWhatOMXDied:
2974        {
2975            ALOGE("OMX/mediaserver died, signalling error!");
2976            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
2977            break;
2978        }
2979
2980        default:
2981            return false;
2982    }
2983
2984    return true;
2985}
2986
2987bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2988    int32_t type;
2989    CHECK(msg->findInt32("type", &type));
2990
2991    IOMX::node_id nodeID;
2992    CHECK(msg->findPointer("node", &nodeID));
2993    CHECK_EQ(nodeID, mCodec->mNode);
2994
2995    switch (type) {
2996        case omx_message::EVENT:
2997        {
2998            int32_t event, data1, data2;
2999            CHECK(msg->findInt32("event", &event));
3000            CHECK(msg->findInt32("data1", &data1));
3001            CHECK(msg->findInt32("data2", &data2));
3002
3003            if (event == OMX_EventCmdComplete
3004                    && data1 == OMX_CommandFlush
3005                    && data2 == (int32_t)OMX_ALL) {
3006                // Use of this notification is not consistent across
3007                // implementations. We'll drop this notification and rely
3008                // on flush-complete notifications on the individual port
3009                // indices instead.
3010
3011                return true;
3012            }
3013
3014            return onOMXEvent(
3015                    static_cast<OMX_EVENTTYPE>(event),
3016                    static_cast<OMX_U32>(data1),
3017                    static_cast<OMX_U32>(data2));
3018        }
3019
3020        case omx_message::EMPTY_BUFFER_DONE:
3021        {
3022            IOMX::buffer_id bufferID;
3023            CHECK(msg->findPointer("buffer", &bufferID));
3024
3025            return onOMXEmptyBufferDone(bufferID);
3026        }
3027
3028        case omx_message::FILL_BUFFER_DONE:
3029        {
3030            IOMX::buffer_id bufferID;
3031            CHECK(msg->findPointer("buffer", &bufferID));
3032
3033            int32_t rangeOffset, rangeLength, flags;
3034            int64_t timeUs;
3035            void *platformPrivate;
3036            void *dataPtr;
3037
3038            CHECK(msg->findInt32("range_offset", &rangeOffset));
3039            CHECK(msg->findInt32("range_length", &rangeLength));
3040            CHECK(msg->findInt32("flags", &flags));
3041            CHECK(msg->findInt64("timestamp", &timeUs));
3042            CHECK(msg->findPointer("platform_private", &platformPrivate));
3043            CHECK(msg->findPointer("data_ptr", &dataPtr));
3044
3045            return onOMXFillBufferDone(
3046                    bufferID,
3047                    (size_t)rangeOffset, (size_t)rangeLength,
3048                    (OMX_U32)flags,
3049                    timeUs,
3050                    platformPrivate,
3051                    dataPtr);
3052        }
3053
3054        default:
3055            TRESPASS();
3056            break;
3057    }
3058}
3059
3060bool ACodec::BaseState::onOMXEvent(
3061        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3062    if (event != OMX_EventError) {
3063        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
3064             mCodec->mComponentName.c_str(), event, data1, data2);
3065
3066        return false;
3067    }
3068
3069    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
3070
3071    mCodec->signalError((OMX_ERRORTYPE)data1);
3072
3073    return true;
3074}
3075
3076bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
3077    ALOGV("[%s] onOMXEmptyBufferDone %p",
3078         mCodec->mComponentName.c_str(), bufferID);
3079
3080    BufferInfo *info =
3081        mCodec->findBufferByID(kPortIndexInput, bufferID);
3082
3083    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3084    info->mStatus = BufferInfo::OWNED_BY_US;
3085
3086    const sp<AMessage> &bufferMeta = info->mData->meta();
3087    void *mediaBuffer;
3088    if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer)
3089            && mediaBuffer != NULL) {
3090        // We're in "store-metadata-in-buffers" mode, the underlying
3091        // OMX component had access to data that's implicitly refcounted
3092        // by this "mediaBuffer" object. Now that the OMX component has
3093        // told us that it's done with the input buffer, we can decrement
3094        // the mediaBuffer's reference count.
3095
3096        ALOGV("releasing mbuf %p", mediaBuffer);
3097
3098        ((MediaBuffer *)mediaBuffer)->release();
3099        mediaBuffer = NULL;
3100
3101        bufferMeta->setPointer("mediaBuffer", NULL);
3102    }
3103
3104    PortMode mode = getPortMode(kPortIndexInput);
3105
3106    switch (mode) {
3107        case KEEP_BUFFERS:
3108            break;
3109
3110        case RESUBMIT_BUFFERS:
3111            postFillThisBuffer(info);
3112            break;
3113
3114        default:
3115        {
3116            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3117            TRESPASS();  // Not currently used
3118            break;
3119        }
3120    }
3121
3122    return true;
3123}
3124
3125void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
3126    if (mCodec->mPortEOS[kPortIndexInput]) {
3127        return;
3128    }
3129
3130    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3131
3132    sp<AMessage> notify = mCodec->mNotify->dup();
3133    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
3134    notify->setPointer("buffer-id", info->mBufferID);
3135
3136    info->mData->meta()->clear();
3137    notify->setBuffer("buffer", info->mData);
3138
3139    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
3140    reply->setPointer("buffer-id", info->mBufferID);
3141
3142    notify->setMessage("reply", reply);
3143
3144    notify->post();
3145
3146    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
3147}
3148
3149void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
3150    IOMX::buffer_id bufferID;
3151    CHECK(msg->findPointer("buffer-id", &bufferID));
3152
3153    sp<ABuffer> buffer;
3154    int32_t err = OK;
3155    bool eos = false;
3156    PortMode mode = getPortMode(kPortIndexInput);
3157
3158    if (!msg->findBuffer("buffer", &buffer)) {
3159        /* these are unfilled buffers returned by client */
3160        CHECK(msg->findInt32("err", &err));
3161
3162        if (err == OK) {
3163            /* buffers with no errors are returned on MediaCodec.flush */
3164            mode = KEEP_BUFFERS;
3165        } else {
3166            ALOGV("[%s] saw error %d instead of an input buffer",
3167                 mCodec->mComponentName.c_str(), err);
3168            eos = true;
3169        }
3170
3171        buffer.clear();
3172    }
3173
3174    int32_t tmp;
3175    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
3176        eos = true;
3177        err = ERROR_END_OF_STREAM;
3178    }
3179
3180    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
3181    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
3182
3183    info->mStatus = BufferInfo::OWNED_BY_US;
3184
3185    switch (mode) {
3186        case KEEP_BUFFERS:
3187        {
3188            if (eos) {
3189                if (!mCodec->mPortEOS[kPortIndexInput]) {
3190                    mCodec->mPortEOS[kPortIndexInput] = true;
3191                    mCodec->mInputEOSResult = err;
3192                }
3193            }
3194            break;
3195        }
3196
3197        case RESUBMIT_BUFFERS:
3198        {
3199            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
3200                int64_t timeUs;
3201                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
3202
3203                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
3204
3205                int32_t isCSD;
3206                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
3207                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
3208                }
3209
3210                if (eos) {
3211                    flags |= OMX_BUFFERFLAG_EOS;
3212                }
3213
3214                if (buffer != info->mData) {
3215                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
3216                         mCodec->mComponentName.c_str(),
3217                         bufferID,
3218                         buffer.get(), info->mData.get());
3219
3220                    CHECK_LE(buffer->size(), info->mData->capacity());
3221                    memcpy(info->mData->data(), buffer->data(), buffer->size());
3222                }
3223
3224                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
3225                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
3226                         mCodec->mComponentName.c_str(), bufferID);
3227                } else if (flags & OMX_BUFFERFLAG_EOS) {
3228                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
3229                         mCodec->mComponentName.c_str(), bufferID);
3230                } else {
3231#if TRACK_BUFFER_TIMING
3232                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
3233                         mCodec->mComponentName.c_str(), bufferID, timeUs);
3234#else
3235                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
3236                         mCodec->mComponentName.c_str(), bufferID, timeUs);
3237#endif
3238                }
3239
3240#if TRACK_BUFFER_TIMING
3241                ACodec::BufferStats stats;
3242                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
3243                stats.mFillBufferDoneTimeUs = -1ll;
3244                mCodec->mBufferStats.add(timeUs, stats);
3245#endif
3246
3247                if (mCodec->mStoreMetaDataInOutputBuffers) {
3248                    // try to submit an output buffer for each input buffer
3249                    PortMode outputMode = getPortMode(kPortIndexOutput);
3250
3251                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
3252                            mCodec->mMetaDataBuffersToSubmit,
3253                            (outputMode == FREE_BUFFERS ? "FREE" :
3254                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
3255                    if (outputMode == RESUBMIT_BUFFERS) {
3256                        CHECK_EQ(mCodec->submitOutputMetaDataBuffer(),
3257                                (status_t)OK);
3258                    }
3259                }
3260
3261                CHECK_EQ(mCodec->mOMX->emptyBuffer(
3262                            mCodec->mNode,
3263                            bufferID,
3264                            0,
3265                            buffer->size(),
3266                            flags,
3267                            timeUs),
3268                         (status_t)OK);
3269
3270                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3271
3272                if (!eos) {
3273                    getMoreInputDataIfPossible();
3274                } else {
3275                    ALOGV("[%s] Signalled EOS on the input port",
3276                         mCodec->mComponentName.c_str());
3277
3278                    mCodec->mPortEOS[kPortIndexInput] = true;
3279                    mCodec->mInputEOSResult = err;
3280                }
3281            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
3282                if (err != ERROR_END_OF_STREAM) {
3283                    ALOGV("[%s] Signalling EOS on the input port "
3284                         "due to error %d",
3285                         mCodec->mComponentName.c_str(), err);
3286                } else {
3287                    ALOGV("[%s] Signalling EOS on the input port",
3288                         mCodec->mComponentName.c_str());
3289                }
3290
3291                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
3292                     mCodec->mComponentName.c_str(), bufferID);
3293
3294                CHECK_EQ(mCodec->mOMX->emptyBuffer(
3295                            mCodec->mNode,
3296                            bufferID,
3297                            0,
3298                            0,
3299                            OMX_BUFFERFLAG_EOS,
3300                            0),
3301                         (status_t)OK);
3302
3303                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3304
3305                mCodec->mPortEOS[kPortIndexInput] = true;
3306                mCodec->mInputEOSResult = err;
3307            }
3308            break;
3309
3310            default:
3311                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3312                break;
3313        }
3314    }
3315}
3316
3317void ACodec::BaseState::getMoreInputDataIfPossible() {
3318    if (mCodec->mPortEOS[kPortIndexInput]) {
3319        return;
3320    }
3321
3322    BufferInfo *eligible = NULL;
3323
3324    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
3325        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
3326
3327#if 0
3328        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
3329            // There's already a "read" pending.
3330            return;
3331        }
3332#endif
3333
3334        if (info->mStatus == BufferInfo::OWNED_BY_US) {
3335            eligible = info;
3336        }
3337    }
3338
3339    if (eligible == NULL) {
3340        return;
3341    }
3342
3343    postFillThisBuffer(eligible);
3344}
3345
3346bool ACodec::BaseState::onOMXFillBufferDone(
3347        IOMX::buffer_id bufferID,
3348        size_t rangeOffset, size_t rangeLength,
3349        OMX_U32 flags,
3350        int64_t timeUs,
3351        void *platformPrivate,
3352        void *dataPtr) {
3353    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
3354         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
3355
3356    ssize_t index;
3357
3358#if TRACK_BUFFER_TIMING
3359    index = mCodec->mBufferStats.indexOfKey(timeUs);
3360    if (index >= 0) {
3361        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
3362        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
3363
3364        ALOGI("frame PTS %lld: %lld",
3365                timeUs,
3366                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
3367
3368        mCodec->mBufferStats.removeItemsAt(index);
3369        stats = NULL;
3370    }
3371#endif
3372
3373    BufferInfo *info =
3374        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
3375
3376    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3377
3378    info->mDequeuedAt = ++mCodec->mDequeueCounter;
3379    info->mStatus = BufferInfo::OWNED_BY_US;
3380
3381    PortMode mode = getPortMode(kPortIndexOutput);
3382
3383    switch (mode) {
3384        case KEEP_BUFFERS:
3385            break;
3386
3387        case RESUBMIT_BUFFERS:
3388        {
3389            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
3390                ALOGV("[%s] calling fillBuffer %p",
3391                     mCodec->mComponentName.c_str(), info->mBufferID);
3392
3393                CHECK_EQ(mCodec->mOMX->fillBuffer(
3394                            mCodec->mNode, info->mBufferID),
3395                         (status_t)OK);
3396
3397                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3398                break;
3399            }
3400
3401            sp<AMessage> reply =
3402                new AMessage(kWhatOutputBufferDrained, mCodec->id());
3403
3404            if (!mCodec->mSentFormat) {
3405                mCodec->sendFormatChange(reply);
3406            }
3407
3408            if (mCodec->mUseMetadataOnEncoderOutput) {
3409                native_handle_t* handle =
3410                        *(native_handle_t**)(info->mData->data() + 4);
3411                info->mData->meta()->setPointer("handle", handle);
3412                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
3413                info->mData->meta()->setInt32("rangeLength", rangeLength);
3414            } else {
3415                info->mData->setRange(rangeOffset, rangeLength);
3416            }
3417#if 0
3418            if (mCodec->mNativeWindow == NULL) {
3419                if (IsIDR(info->mData)) {
3420                    ALOGI("IDR frame");
3421                }
3422            }
3423#endif
3424
3425            if (mCodec->mSkipCutBuffer != NULL) {
3426                mCodec->mSkipCutBuffer->submit(info->mData);
3427            }
3428            info->mData->meta()->setInt64("timeUs", timeUs);
3429
3430            sp<AMessage> notify = mCodec->mNotify->dup();
3431            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
3432            notify->setPointer("buffer-id", info->mBufferID);
3433            notify->setBuffer("buffer", info->mData);
3434            notify->setInt32("flags", flags);
3435
3436            reply->setPointer("buffer-id", info->mBufferID);
3437
3438            notify->setMessage("reply", reply);
3439
3440            notify->post();
3441
3442            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
3443
3444            if (flags & OMX_BUFFERFLAG_EOS) {
3445                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
3446
3447                sp<AMessage> notify = mCodec->mNotify->dup();
3448                notify->setInt32("what", ACodec::kWhatEOS);
3449                notify->setInt32("err", mCodec->mInputEOSResult);
3450                notify->post();
3451
3452                mCodec->mPortEOS[kPortIndexOutput] = true;
3453            }
3454            break;
3455        }
3456
3457        default:
3458        {
3459            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3460
3461            CHECK_EQ((status_t)OK,
3462                     mCodec->freeBuffer(kPortIndexOutput, index));
3463            break;
3464        }
3465    }
3466
3467    return true;
3468}
3469
3470void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
3471    IOMX::buffer_id bufferID;
3472    CHECK(msg->findPointer("buffer-id", &bufferID));
3473
3474    ssize_t index;
3475    BufferInfo *info =
3476        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
3477    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
3478
3479    android_native_rect_t crop;
3480    if (msg->findRect("crop",
3481            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
3482        CHECK_EQ(0, native_window_set_crop(
3483                mCodec->mNativeWindow.get(), &crop));
3484    }
3485
3486    int32_t render;
3487    if (mCodec->mNativeWindow != NULL
3488            && msg->findInt32("render", &render) && render != 0
3489            && (info->mData == NULL || info->mData->size() != 0)) {
3490        // The client wants this buffer to be rendered.
3491
3492        status_t err;
3493        if ((err = mCodec->mNativeWindow->queueBuffer(
3494                    mCodec->mNativeWindow.get(),
3495                    info->mGraphicBuffer.get(), -1)) == OK) {
3496            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
3497        } else {
3498            mCodec->signalError(OMX_ErrorUndefined, err);
3499            info->mStatus = BufferInfo::OWNED_BY_US;
3500        }
3501    } else {
3502        info->mStatus = BufferInfo::OWNED_BY_US;
3503    }
3504
3505    PortMode mode = getPortMode(kPortIndexOutput);
3506
3507    switch (mode) {
3508        case KEEP_BUFFERS:
3509        {
3510            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
3511
3512            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3513                // We cannot resubmit the buffer we just rendered, dequeue
3514                // the spare instead.
3515
3516                info = mCodec->dequeueBufferFromNativeWindow();
3517            }
3518            break;
3519        }
3520
3521        case RESUBMIT_BUFFERS:
3522        {
3523            if (!mCodec->mPortEOS[kPortIndexOutput]) {
3524                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3525                    // We cannot resubmit the buffer we just rendered, dequeue
3526                    // the spare instead.
3527
3528                    info = mCodec->dequeueBufferFromNativeWindow();
3529                }
3530
3531                if (info != NULL) {
3532                    ALOGV("[%s] calling fillBuffer %p",
3533                         mCodec->mComponentName.c_str(), info->mBufferID);
3534
3535                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3536                             (status_t)OK);
3537
3538                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3539                }
3540            }
3541            break;
3542        }
3543
3544        default:
3545        {
3546            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3547
3548            CHECK_EQ((status_t)OK,
3549                     mCodec->freeBuffer(kPortIndexOutput, index));
3550            break;
3551        }
3552    }
3553}
3554
3555////////////////////////////////////////////////////////////////////////////////
3556
3557ACodec::UninitializedState::UninitializedState(ACodec *codec)
3558    : BaseState(codec) {
3559}
3560
3561void ACodec::UninitializedState::stateEntered() {
3562    ALOGV("Now uninitialized");
3563
3564    if (mDeathNotifier != NULL) {
3565        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
3566        mDeathNotifier.clear();
3567    }
3568
3569    mCodec->mNativeWindow.clear();
3570    mCodec->mNode = NULL;
3571    mCodec->mOMX.clear();
3572    mCodec->mQuirks = 0;
3573    mCodec->mFlags = 0;
3574    mCodec->mUseMetadataOnEncoderOutput = 0;
3575    mCodec->mComponentName.clear();
3576}
3577
3578bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
3579    bool handled = false;
3580
3581    switch (msg->what()) {
3582        case ACodec::kWhatSetup:
3583        {
3584            onSetup(msg);
3585
3586            handled = true;
3587            break;
3588        }
3589
3590        case ACodec::kWhatAllocateComponent:
3591        {
3592            onAllocateComponent(msg);
3593            handled = true;
3594            break;
3595        }
3596
3597        case ACodec::kWhatShutdown:
3598        {
3599            int32_t keepComponentAllocated;
3600            CHECK(msg->findInt32(
3601                        "keepComponentAllocated", &keepComponentAllocated));
3602            CHECK(!keepComponentAllocated);
3603
3604            sp<AMessage> notify = mCodec->mNotify->dup();
3605            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3606            notify->post();
3607
3608            handled = true;
3609            break;
3610        }
3611
3612        case ACodec::kWhatFlush:
3613        {
3614            sp<AMessage> notify = mCodec->mNotify->dup();
3615            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3616            notify->post();
3617
3618            handled = true;
3619            break;
3620        }
3621
3622        default:
3623            return BaseState::onMessageReceived(msg);
3624    }
3625
3626    return handled;
3627}
3628
3629void ACodec::UninitializedState::onSetup(
3630        const sp<AMessage> &msg) {
3631    if (onAllocateComponent(msg)
3632            && mCodec->mLoadedState->onConfigureComponent(msg)) {
3633        mCodec->mLoadedState->onStart();
3634    }
3635}
3636
3637bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
3638    ALOGV("onAllocateComponent");
3639
3640    CHECK(mCodec->mNode == NULL);
3641
3642    OMXClient client;
3643    CHECK_EQ(client.connect(), (status_t)OK);
3644
3645    sp<IOMX> omx = client.interface();
3646
3647    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
3648
3649    mDeathNotifier = new DeathNotifier(notify);
3650    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
3651        // This was a local binder, if it dies so do we, we won't care
3652        // about any notifications in the afterlife.
3653        mDeathNotifier.clear();
3654    }
3655
3656    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
3657
3658    AString mime;
3659
3660    AString componentName;
3661    uint32_t quirks = 0;
3662    if (msg->findString("componentName", &componentName)) {
3663        ssize_t index = matchingCodecs.add();
3664        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
3665        entry->mName = String8(componentName.c_str());
3666
3667        if (!OMXCodec::findCodecQuirks(
3668                    componentName.c_str(), &entry->mQuirks)) {
3669            entry->mQuirks = 0;
3670        }
3671    } else {
3672        CHECK(msg->findString("mime", &mime));
3673
3674        int32_t encoder;
3675        if (!msg->findInt32("encoder", &encoder)) {
3676            encoder = false;
3677        }
3678
3679        OMXCodec::findMatchingCodecs(
3680                mime.c_str(),
3681                encoder, // createEncoder
3682                NULL,  // matchComponentName
3683                0,     // flags
3684                &matchingCodecs);
3685    }
3686
3687    sp<CodecObserver> observer = new CodecObserver;
3688    IOMX::node_id node = NULL;
3689
3690    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
3691            ++matchIndex) {
3692        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
3693        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
3694
3695        pid_t tid = androidGetTid();
3696        int prevPriority = androidGetThreadPriority(tid);
3697        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
3698        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
3699        androidSetThreadPriority(tid, prevPriority);
3700
3701        if (err == OK) {
3702            break;
3703        }
3704
3705        node = NULL;
3706    }
3707
3708    if (node == NULL) {
3709        if (!mime.empty()) {
3710            ALOGE("Unable to instantiate a decoder for type '%s'.",
3711                 mime.c_str());
3712        } else {
3713            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
3714        }
3715
3716        mCodec->signalError(OMX_ErrorComponentNotFound);
3717        return false;
3718    }
3719
3720    notify = new AMessage(kWhatOMXMessage, mCodec->id());
3721    observer->setNotificationMessage(notify);
3722
3723    mCodec->mComponentName = componentName;
3724    mCodec->mFlags = 0;
3725
3726    if (componentName.endsWith(".secure")) {
3727        mCodec->mFlags |= kFlagIsSecure;
3728        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
3729    }
3730
3731    mCodec->mQuirks = quirks;
3732    mCodec->mOMX = omx;
3733    mCodec->mNode = node;
3734
3735    {
3736        sp<AMessage> notify = mCodec->mNotify->dup();
3737        notify->setInt32("what", ACodec::kWhatComponentAllocated);
3738        notify->setString("componentName", mCodec->mComponentName.c_str());
3739        notify->post();
3740    }
3741
3742    mCodec->changeState(mCodec->mLoadedState);
3743
3744    return true;
3745}
3746
3747////////////////////////////////////////////////////////////////////////////////
3748
3749ACodec::LoadedState::LoadedState(ACodec *codec)
3750    : BaseState(codec) {
3751}
3752
3753void ACodec::LoadedState::stateEntered() {
3754    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
3755
3756    mCodec->mPortEOS[kPortIndexInput] =
3757        mCodec->mPortEOS[kPortIndexOutput] = false;
3758
3759    mCodec->mInputEOSResult = OK;
3760
3761    mCodec->mDequeueCounter = 0;
3762    mCodec->mMetaDataBuffersToSubmit = 0;
3763    mCodec->mRepeatFrameDelayUs = -1ll;
3764
3765    if (mCodec->mShutdownInProgress) {
3766        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
3767
3768        mCodec->mShutdownInProgress = false;
3769        mCodec->mKeepComponentAllocated = false;
3770
3771        onShutdown(keepComponentAllocated);
3772    }
3773}
3774
3775void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
3776    if (!keepComponentAllocated) {
3777        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
3778
3779        mCodec->changeState(mCodec->mUninitializedState);
3780    }
3781
3782    sp<AMessage> notify = mCodec->mNotify->dup();
3783    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3784    notify->post();
3785}
3786
3787bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
3788    bool handled = false;
3789
3790    switch (msg->what()) {
3791        case ACodec::kWhatConfigureComponent:
3792        {
3793            onConfigureComponent(msg);
3794            handled = true;
3795            break;
3796        }
3797
3798        case ACodec::kWhatCreateInputSurface:
3799        {
3800            onCreateInputSurface(msg);
3801            handled = true;
3802            break;
3803        }
3804
3805        case ACodec::kWhatStart:
3806        {
3807            onStart();
3808            handled = true;
3809            break;
3810        }
3811
3812        case ACodec::kWhatShutdown:
3813        {
3814            int32_t keepComponentAllocated;
3815            CHECK(msg->findInt32(
3816                        "keepComponentAllocated", &keepComponentAllocated));
3817
3818            onShutdown(keepComponentAllocated);
3819
3820            handled = true;
3821            break;
3822        }
3823
3824        case ACodec::kWhatFlush:
3825        {
3826            sp<AMessage> notify = mCodec->mNotify->dup();
3827            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3828            notify->post();
3829
3830            handled = true;
3831            break;
3832        }
3833
3834        default:
3835            return BaseState::onMessageReceived(msg);
3836    }
3837
3838    return handled;
3839}
3840
3841bool ACodec::LoadedState::onConfigureComponent(
3842        const sp<AMessage> &msg) {
3843    ALOGV("onConfigureComponent");
3844
3845    CHECK(mCodec->mNode != NULL);
3846
3847    AString mime;
3848    CHECK(msg->findString("mime", &mime));
3849
3850    status_t err = mCodec->configureCodec(mime.c_str(), msg);
3851
3852    if (err != OK) {
3853        ALOGE("[%s] configureCodec returning error %d",
3854              mCodec->mComponentName.c_str(), err);
3855
3856        mCodec->signalError(OMX_ErrorUndefined, err);
3857        return false;
3858    }
3859
3860    sp<RefBase> obj;
3861    if (msg->findObject("native-window", &obj)
3862            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
3863        sp<NativeWindowWrapper> nativeWindow(
3864                static_cast<NativeWindowWrapper *>(obj.get()));
3865        CHECK(nativeWindow != NULL);
3866        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
3867
3868        native_window_set_scaling_mode(
3869                mCodec->mNativeWindow.get(),
3870                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3871    }
3872    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
3873
3874    {
3875        sp<AMessage> notify = mCodec->mNotify->dup();
3876        notify->setInt32("what", ACodec::kWhatComponentConfigured);
3877        notify->post();
3878    }
3879
3880    return true;
3881}
3882
3883void ACodec::LoadedState::onCreateInputSurface(
3884        const sp<AMessage> &msg) {
3885    ALOGV("onCreateInputSurface");
3886
3887    sp<AMessage> notify = mCodec->mNotify->dup();
3888    notify->setInt32("what", ACodec::kWhatInputSurfaceCreated);
3889
3890    sp<IGraphicBufferProducer> bufferProducer;
3891    status_t err;
3892
3893    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
3894            &bufferProducer);
3895
3896    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
3897        err = mCodec->mOMX->setInternalOption(
3898                mCodec->mNode,
3899                kPortIndexInput,
3900                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
3901                &mCodec->mRepeatFrameDelayUs,
3902                sizeof(mCodec->mRepeatFrameDelayUs));
3903
3904        if (err != OK) {
3905            ALOGE("[%s] Unable to configure option to repeat previous "
3906                  "frames (err %d)",
3907                  mCodec->mComponentName.c_str(),
3908                  err);
3909        }
3910    }
3911
3912    if (err == OK) {
3913        notify->setObject("input-surface",
3914                new BufferProducerWrapper(bufferProducer));
3915    } else {
3916        // Can't use mCodec->signalError() here -- MediaCodec won't forward
3917        // the error through because it's in the "configured" state.  We
3918        // send a kWhatInputSurfaceCreated with an error value instead.
3919        ALOGE("[%s] onCreateInputSurface returning error %d",
3920                mCodec->mComponentName.c_str(), err);
3921        notify->setInt32("err", err);
3922    }
3923    notify->post();
3924}
3925
3926void ACodec::LoadedState::onStart() {
3927    ALOGV("onStart");
3928
3929    CHECK_EQ(mCodec->mOMX->sendCommand(
3930                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3931             (status_t)OK);
3932
3933    mCodec->changeState(mCodec->mLoadedToIdleState);
3934}
3935
3936////////////////////////////////////////////////////////////////////////////////
3937
3938ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
3939    : BaseState(codec) {
3940}
3941
3942void ACodec::LoadedToIdleState::stateEntered() {
3943    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
3944
3945    status_t err;
3946    if ((err = allocateBuffers()) != OK) {
3947        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
3948             "(error 0x%08x)",
3949             err);
3950
3951        mCodec->signalError(OMX_ErrorUndefined, err);
3952
3953        mCodec->changeState(mCodec->mLoadedState);
3954    }
3955}
3956
3957status_t ACodec::LoadedToIdleState::allocateBuffers() {
3958    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
3959
3960    if (err != OK) {
3961        return err;
3962    }
3963
3964    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
3965}
3966
3967bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3968    switch (msg->what()) {
3969        case kWhatShutdown:
3970        {
3971            mCodec->deferMessage(msg);
3972            return true;
3973        }
3974
3975        case kWhatSignalEndOfInputStream:
3976        {
3977            mCodec->onSignalEndOfInputStream();
3978            return true;
3979        }
3980
3981        case kWhatResume:
3982        {
3983            // We'll be active soon enough.
3984            return true;
3985        }
3986
3987        case kWhatFlush:
3988        {
3989            // We haven't even started yet, so we're flushed alright...
3990            sp<AMessage> notify = mCodec->mNotify->dup();
3991            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3992            notify->post();
3993            return true;
3994        }
3995
3996        default:
3997            return BaseState::onMessageReceived(msg);
3998    }
3999}
4000
4001bool ACodec::LoadedToIdleState::onOMXEvent(
4002        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4003    switch (event) {
4004        case OMX_EventCmdComplete:
4005        {
4006            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4007            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
4008
4009            CHECK_EQ(mCodec->mOMX->sendCommand(
4010                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
4011                     (status_t)OK);
4012
4013            mCodec->changeState(mCodec->mIdleToExecutingState);
4014
4015            return true;
4016        }
4017
4018        default:
4019            return BaseState::onOMXEvent(event, data1, data2);
4020    }
4021}
4022
4023////////////////////////////////////////////////////////////////////////////////
4024
4025ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
4026    : BaseState(codec) {
4027}
4028
4029void ACodec::IdleToExecutingState::stateEntered() {
4030    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
4031}
4032
4033bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4034    switch (msg->what()) {
4035        case kWhatShutdown:
4036        {
4037            mCodec->deferMessage(msg);
4038            return true;
4039        }
4040
4041        case kWhatResume:
4042        {
4043            // We'll be active soon enough.
4044            return true;
4045        }
4046
4047        case kWhatFlush:
4048        {
4049            // We haven't even started yet, so we're flushed alright...
4050            sp<AMessage> notify = mCodec->mNotify->dup();
4051            notify->setInt32("what", ACodec::kWhatFlushCompleted);
4052            notify->post();
4053
4054            return true;
4055        }
4056
4057        case kWhatSignalEndOfInputStream:
4058        {
4059            mCodec->onSignalEndOfInputStream();
4060            return true;
4061        }
4062
4063        default:
4064            return BaseState::onMessageReceived(msg);
4065    }
4066}
4067
4068bool ACodec::IdleToExecutingState::onOMXEvent(
4069        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4070    switch (event) {
4071        case OMX_EventCmdComplete:
4072        {
4073            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4074            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
4075
4076            mCodec->mExecutingState->resume();
4077            mCodec->changeState(mCodec->mExecutingState);
4078
4079            return true;
4080        }
4081
4082        default:
4083            return BaseState::onOMXEvent(event, data1, data2);
4084    }
4085}
4086
4087////////////////////////////////////////////////////////////////////////////////
4088
4089ACodec::ExecutingState::ExecutingState(ACodec *codec)
4090    : BaseState(codec),
4091      mActive(false) {
4092}
4093
4094ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
4095        OMX_U32 portIndex) {
4096    return RESUBMIT_BUFFERS;
4097}
4098
4099void ACodec::ExecutingState::submitOutputMetaBuffers() {
4100    // submit as many buffers as there are input buffers with the codec
4101    // in case we are in port reconfiguring
4102    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4103        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4104
4105        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4106            if (mCodec->submitOutputMetaDataBuffer() != OK)
4107                break;
4108        }
4109    }
4110}
4111
4112void ACodec::ExecutingState::submitRegularOutputBuffers() {
4113    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
4114        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
4115
4116        if (mCodec->mNativeWindow != NULL) {
4117            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
4118                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
4119
4120            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4121                continue;
4122            }
4123        } else {
4124            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4125        }
4126
4127        ALOGV("[%s] calling fillBuffer %p",
4128             mCodec->mComponentName.c_str(), info->mBufferID);
4129
4130        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4131                 (status_t)OK);
4132
4133        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4134    }
4135}
4136
4137void ACodec::ExecutingState::submitOutputBuffers() {
4138    submitRegularOutputBuffers();
4139    if (mCodec->mStoreMetaDataInOutputBuffers) {
4140        submitOutputMetaBuffers();
4141    }
4142}
4143
4144void ACodec::ExecutingState::resume() {
4145    if (mActive) {
4146        ALOGV("[%s] We're already active, no need to resume.",
4147             mCodec->mComponentName.c_str());
4148
4149        return;
4150    }
4151
4152    submitOutputBuffers();
4153
4154    // Post the first input buffer.
4155    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
4156    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
4157
4158    postFillThisBuffer(info);
4159
4160    mActive = true;
4161}
4162
4163void ACodec::ExecutingState::stateEntered() {
4164    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
4165
4166    mCodec->processDeferredMessages();
4167}
4168
4169bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4170    bool handled = false;
4171
4172    switch (msg->what()) {
4173        case kWhatShutdown:
4174        {
4175            int32_t keepComponentAllocated;
4176            CHECK(msg->findInt32(
4177                        "keepComponentAllocated", &keepComponentAllocated));
4178
4179            mCodec->mShutdownInProgress = true;
4180            mCodec->mKeepComponentAllocated = keepComponentAllocated;
4181
4182            mActive = false;
4183
4184            CHECK_EQ(mCodec->mOMX->sendCommand(
4185                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4186                     (status_t)OK);
4187
4188            mCodec->changeState(mCodec->mExecutingToIdleState);
4189
4190            handled = true;
4191            break;
4192        }
4193
4194        case kWhatFlush:
4195        {
4196            ALOGV("[%s] ExecutingState flushing now "
4197                 "(codec owns %d/%d input, %d/%d output).",
4198                    mCodec->mComponentName.c_str(),
4199                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
4200                    mCodec->mBuffers[kPortIndexInput].size(),
4201                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
4202                    mCodec->mBuffers[kPortIndexOutput].size());
4203
4204            mActive = false;
4205
4206            CHECK_EQ(mCodec->mOMX->sendCommand(
4207                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
4208                     (status_t)OK);
4209
4210            mCodec->changeState(mCodec->mFlushingState);
4211            handled = true;
4212            break;
4213        }
4214
4215        case kWhatResume:
4216        {
4217            resume();
4218
4219            handled = true;
4220            break;
4221        }
4222
4223        case kWhatRequestIDRFrame:
4224        {
4225            status_t err = mCodec->requestIDRFrame();
4226            if (err != OK) {
4227                ALOGW("Requesting an IDR frame failed.");
4228            }
4229
4230            handled = true;
4231            break;
4232        }
4233
4234        case kWhatSetParameters:
4235        {
4236            sp<AMessage> params;
4237            CHECK(msg->findMessage("params", &params));
4238
4239            status_t err = mCodec->setParameters(params);
4240
4241            sp<AMessage> reply;
4242            if (msg->findMessage("reply", &reply)) {
4243                reply->setInt32("err", err);
4244                reply->post();
4245            }
4246
4247            handled = true;
4248            break;
4249        }
4250
4251        case ACodec::kWhatSignalEndOfInputStream:
4252        {
4253            mCodec->onSignalEndOfInputStream();
4254            handled = true;
4255            break;
4256        }
4257
4258        default:
4259            handled = BaseState::onMessageReceived(msg);
4260            break;
4261    }
4262
4263    return handled;
4264}
4265
4266status_t ACodec::setParameters(const sp<AMessage> &params) {
4267    int32_t videoBitrate;
4268    if (params->findInt32("video-bitrate", &videoBitrate)) {
4269        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
4270        InitOMXParams(&configParams);
4271        configParams.nPortIndex = kPortIndexOutput;
4272        configParams.nEncodeBitrate = videoBitrate;
4273
4274        status_t err = mOMX->setConfig(
4275                mNode,
4276                OMX_IndexConfigVideoBitrate,
4277                &configParams,
4278                sizeof(configParams));
4279
4280        if (err != OK) {
4281            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
4282                   videoBitrate, err);
4283
4284            return err;
4285        }
4286    }
4287
4288    int32_t dropInputFrames;
4289    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
4290        bool suspend = dropInputFrames != 0;
4291
4292        status_t err =
4293            mOMX->setInternalOption(
4294                     mNode,
4295                     kPortIndexInput,
4296                     IOMX::INTERNAL_OPTION_SUSPEND,
4297                     &suspend,
4298                     sizeof(suspend));
4299
4300        if (err != OK) {
4301            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
4302            return err;
4303        }
4304    }
4305
4306    int32_t dummy;
4307    if (params->findInt32("request-sync", &dummy)) {
4308        status_t err = requestIDRFrame();
4309
4310        if (err != OK) {
4311            ALOGE("Requesting a sync frame failed w/ err %d", err);
4312            return err;
4313        }
4314    }
4315
4316    return OK;
4317}
4318
4319void ACodec::onSignalEndOfInputStream() {
4320    sp<AMessage> notify = mNotify->dup();
4321    notify->setInt32("what", ACodec::kWhatSignaledInputEOS);
4322
4323    status_t err = mOMX->signalEndOfInputStream(mNode);
4324    if (err != OK) {
4325        notify->setInt32("err", err);
4326    }
4327    notify->post();
4328}
4329
4330bool ACodec::ExecutingState::onOMXEvent(
4331        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4332    switch (event) {
4333        case OMX_EventPortSettingsChanged:
4334        {
4335            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
4336
4337            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
4338                mCodec->mMetaDataBuffersToSubmit = 0;
4339                CHECK_EQ(mCodec->mOMX->sendCommand(
4340                            mCodec->mNode,
4341                            OMX_CommandPortDisable, kPortIndexOutput),
4342                         (status_t)OK);
4343
4344                mCodec->freeOutputBuffersNotOwnedByComponent();
4345
4346                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
4347            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
4348                mCodec->mSentFormat = false;
4349            } else {
4350                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
4351                     mCodec->mComponentName.c_str(), data2);
4352            }
4353
4354            return true;
4355        }
4356
4357        case OMX_EventBufferFlag:
4358        {
4359            return true;
4360        }
4361
4362        default:
4363            return BaseState::onOMXEvent(event, data1, data2);
4364    }
4365}
4366
4367////////////////////////////////////////////////////////////////////////////////
4368
4369ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
4370        ACodec *codec)
4371    : BaseState(codec) {
4372}
4373
4374ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
4375        OMX_U32 portIndex) {
4376    if (portIndex == kPortIndexOutput) {
4377        return FREE_BUFFERS;
4378    }
4379
4380    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
4381
4382    return RESUBMIT_BUFFERS;
4383}
4384
4385bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
4386        const sp<AMessage> &msg) {
4387    bool handled = false;
4388
4389    switch (msg->what()) {
4390        case kWhatFlush:
4391        case kWhatShutdown:
4392        case kWhatResume:
4393        {
4394            if (msg->what() == kWhatResume) {
4395                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
4396            }
4397
4398            mCodec->deferMessage(msg);
4399            handled = true;
4400            break;
4401        }
4402
4403        default:
4404            handled = BaseState::onMessageReceived(msg);
4405            break;
4406    }
4407
4408    return handled;
4409}
4410
4411void ACodec::OutputPortSettingsChangedState::stateEntered() {
4412    ALOGV("[%s] Now handling output port settings change",
4413         mCodec->mComponentName.c_str());
4414}
4415
4416bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
4417        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4418    switch (event) {
4419        case OMX_EventCmdComplete:
4420        {
4421            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
4422                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
4423
4424                ALOGV("[%s] Output port now disabled.",
4425                        mCodec->mComponentName.c_str());
4426
4427                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
4428                mCodec->mDealer[kPortIndexOutput].clear();
4429
4430                CHECK_EQ(mCodec->mOMX->sendCommand(
4431                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
4432                         (status_t)OK);
4433
4434                status_t err;
4435                if ((err = mCodec->allocateBuffersOnPort(
4436                                kPortIndexOutput)) != OK) {
4437                    ALOGE("Failed to allocate output port buffers after "
4438                         "port reconfiguration (error 0x%08x)",
4439                         err);
4440
4441                    mCodec->signalError(OMX_ErrorUndefined, err);
4442
4443                    // This is technically not correct, but appears to be
4444                    // the only way to free the component instance.
4445                    // Controlled transitioning from excecuting->idle
4446                    // and idle->loaded seem impossible probably because
4447                    // the output port never finishes re-enabling.
4448                    mCodec->mShutdownInProgress = true;
4449                    mCodec->mKeepComponentAllocated = false;
4450                    mCodec->changeState(mCodec->mLoadedState);
4451                }
4452
4453                return true;
4454            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
4455                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
4456
4457                mCodec->mSentFormat = false;
4458
4459                ALOGV("[%s] Output port now reenabled.",
4460                        mCodec->mComponentName.c_str());
4461
4462                if (mCodec->mExecutingState->active()) {
4463                    mCodec->mExecutingState->submitOutputBuffers();
4464                }
4465
4466                mCodec->changeState(mCodec->mExecutingState);
4467
4468                return true;
4469            }
4470
4471            return false;
4472        }
4473
4474        default:
4475            return false;
4476    }
4477}
4478
4479////////////////////////////////////////////////////////////////////////////////
4480
4481ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
4482    : BaseState(codec),
4483      mComponentNowIdle(false) {
4484}
4485
4486bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
4487    bool handled = false;
4488
4489    switch (msg->what()) {
4490        case kWhatFlush:
4491        {
4492            // Don't send me a flush request if you previously wanted me
4493            // to shutdown.
4494            TRESPASS();
4495            break;
4496        }
4497
4498        case kWhatShutdown:
4499        {
4500            // We're already doing that...
4501
4502            handled = true;
4503            break;
4504        }
4505
4506        default:
4507            handled = BaseState::onMessageReceived(msg);
4508            break;
4509    }
4510
4511    return handled;
4512}
4513
4514void ACodec::ExecutingToIdleState::stateEntered() {
4515    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
4516
4517    mComponentNowIdle = false;
4518    mCodec->mSentFormat = false;
4519}
4520
4521bool ACodec::ExecutingToIdleState::onOMXEvent(
4522        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4523    switch (event) {
4524        case OMX_EventCmdComplete:
4525        {
4526            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4527            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
4528
4529            mComponentNowIdle = true;
4530
4531            changeStateIfWeOwnAllBuffers();
4532
4533            return true;
4534        }
4535
4536        case OMX_EventPortSettingsChanged:
4537        case OMX_EventBufferFlag:
4538        {
4539            // We're shutting down and don't care about this anymore.
4540            return true;
4541        }
4542
4543        default:
4544            return BaseState::onOMXEvent(event, data1, data2);
4545    }
4546}
4547
4548void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
4549    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
4550        CHECK_EQ(mCodec->mOMX->sendCommand(
4551                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
4552                 (status_t)OK);
4553
4554        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
4555        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
4556
4557        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
4558                && mCodec->mNativeWindow != NULL) {
4559            // We push enough 1x1 blank buffers to ensure that one of
4560            // them has made it to the display.  This allows the OMX
4561            // component teardown to zero out any protected buffers
4562            // without the risk of scanning out one of those buffers.
4563            mCodec->pushBlankBuffersToNativeWindow();
4564        }
4565
4566        mCodec->changeState(mCodec->mIdleToLoadedState);
4567    }
4568}
4569
4570void ACodec::ExecutingToIdleState::onInputBufferFilled(
4571        const sp<AMessage> &msg) {
4572    BaseState::onInputBufferFilled(msg);
4573
4574    changeStateIfWeOwnAllBuffers();
4575}
4576
4577void ACodec::ExecutingToIdleState::onOutputBufferDrained(
4578        const sp<AMessage> &msg) {
4579    BaseState::onOutputBufferDrained(msg);
4580
4581    changeStateIfWeOwnAllBuffers();
4582}
4583
4584////////////////////////////////////////////////////////////////////////////////
4585
4586ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
4587    : BaseState(codec) {
4588}
4589
4590bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
4591    bool handled = false;
4592
4593    switch (msg->what()) {
4594        case kWhatShutdown:
4595        {
4596            // We're already doing that...
4597
4598            handled = true;
4599            break;
4600        }
4601
4602        case kWhatFlush:
4603        {
4604            // Don't send me a flush request if you previously wanted me
4605            // to shutdown.
4606            TRESPASS();
4607            break;
4608        }
4609
4610        default:
4611            handled = BaseState::onMessageReceived(msg);
4612            break;
4613    }
4614
4615    return handled;
4616}
4617
4618void ACodec::IdleToLoadedState::stateEntered() {
4619    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
4620}
4621
4622bool ACodec::IdleToLoadedState::onOMXEvent(
4623        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4624    switch (event) {
4625        case OMX_EventCmdComplete:
4626        {
4627            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4628            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
4629
4630            mCodec->changeState(mCodec->mLoadedState);
4631
4632            return true;
4633        }
4634
4635        default:
4636            return BaseState::onOMXEvent(event, data1, data2);
4637    }
4638}
4639
4640////////////////////////////////////////////////////////////////////////////////
4641
4642ACodec::FlushingState::FlushingState(ACodec *codec)
4643    : BaseState(codec) {
4644}
4645
4646void ACodec::FlushingState::stateEntered() {
4647    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
4648
4649    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
4650}
4651
4652bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
4653    bool handled = false;
4654
4655    switch (msg->what()) {
4656        case kWhatShutdown:
4657        {
4658            mCodec->deferMessage(msg);
4659            break;
4660        }
4661
4662        case kWhatFlush:
4663        {
4664            // We're already doing this right now.
4665            handled = true;
4666            break;
4667        }
4668
4669        default:
4670            handled = BaseState::onMessageReceived(msg);
4671            break;
4672    }
4673
4674    return handled;
4675}
4676
4677bool ACodec::FlushingState::onOMXEvent(
4678        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4679    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
4680            mCodec->mComponentName.c_str(), event, data1);
4681
4682    switch (event) {
4683        case OMX_EventCmdComplete:
4684        {
4685            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
4686
4687            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
4688                CHECK(!mFlushComplete[data2]);
4689                mFlushComplete[data2] = true;
4690
4691                if (mFlushComplete[kPortIndexInput]
4692                        && mFlushComplete[kPortIndexOutput]) {
4693                    changeStateIfWeOwnAllBuffers();
4694                }
4695            } else {
4696                CHECK_EQ(data2, OMX_ALL);
4697                CHECK(mFlushComplete[kPortIndexInput]);
4698                CHECK(mFlushComplete[kPortIndexOutput]);
4699
4700                changeStateIfWeOwnAllBuffers();
4701            }
4702
4703            return true;
4704        }
4705
4706        case OMX_EventPortSettingsChanged:
4707        {
4708            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
4709            msg->setInt32("type", omx_message::EVENT);
4710            msg->setPointer("node", mCodec->mNode);
4711            msg->setInt32("event", event);
4712            msg->setInt32("data1", data1);
4713            msg->setInt32("data2", data2);
4714
4715            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
4716                 mCodec->mComponentName.c_str());
4717
4718            mCodec->deferMessage(msg);
4719
4720            return true;
4721        }
4722
4723        default:
4724            return BaseState::onOMXEvent(event, data1, data2);
4725    }
4726
4727    return true;
4728}
4729
4730void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
4731    BaseState::onOutputBufferDrained(msg);
4732
4733    changeStateIfWeOwnAllBuffers();
4734}
4735
4736void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
4737    BaseState::onInputBufferFilled(msg);
4738
4739    changeStateIfWeOwnAllBuffers();
4740}
4741
4742void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
4743    if (mFlushComplete[kPortIndexInput]
4744            && mFlushComplete[kPortIndexOutput]
4745            && mCodec->allYourBuffersAreBelongToUs()) {
4746        // We now own all buffers except possibly those still queued with
4747        // the native window for rendering. Let's get those back as well.
4748        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
4749
4750        sp<AMessage> notify = mCodec->mNotify->dup();
4751        notify->setInt32("what", ACodec::kWhatFlushCompleted);
4752        notify->post();
4753
4754        mCodec->mPortEOS[kPortIndexInput] =
4755            mCodec->mPortEOS[kPortIndexOutput] = false;
4756
4757        mCodec->mInputEOSResult = OK;
4758
4759        if (mCodec->mSkipCutBuffer != NULL) {
4760            mCodec->mSkipCutBuffer->clear();
4761        }
4762
4763        mCodec->changeState(mCodec->mExecutingState);
4764    }
4765}
4766
4767}  // namespace android
4768