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