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