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