ACodec.cpp revision dc9bacd838442a524585887e6ea6696836be2eda
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "ACodec"
19
20#include <media/stagefright/ACodec.h>
21
22#include <binder/MemoryDealer.h>
23
24#include <media/stagefright/foundation/hexdump.h>
25#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28
29#include <media/stagefright/MediaDefs.h>
30#include <media/stagefright/NativeWindowWrapper.h>
31#include <media/stagefright/OMXClient.h>
32#include <media/stagefright/OMXCodec.h>
33
34#include <surfaceflinger/Surface.h>
35#include <gui/SurfaceTextureClient.h>
36
37#include <OMX_Component.h>
38
39namespace android {
40
41template<class T>
42static void InitOMXParams(T *params) {
43    params->nSize = sizeof(T);
44    params->nVersion.s.nVersionMajor = 1;
45    params->nVersion.s.nVersionMinor = 0;
46    params->nVersion.s.nRevision = 0;
47    params->nVersion.s.nStep = 0;
48}
49
50struct CodecObserver : public BnOMXObserver {
51    CodecObserver() {}
52
53    void setNotificationMessage(const sp<AMessage> &msg) {
54        mNotify = msg;
55    }
56
57    // from IOMXObserver
58    virtual void onMessage(const omx_message &omx_msg) {
59        sp<AMessage> msg = mNotify->dup();
60
61        msg->setInt32("type", omx_msg.type);
62        msg->setPointer("node", omx_msg.node);
63
64        switch (omx_msg.type) {
65            case omx_message::EVENT:
66            {
67                msg->setInt32("event", omx_msg.u.event_data.event);
68                msg->setInt32("data1", omx_msg.u.event_data.data1);
69                msg->setInt32("data2", omx_msg.u.event_data.data2);
70                break;
71            }
72
73            case omx_message::EMPTY_BUFFER_DONE:
74            {
75                msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
76                break;
77            }
78
79            case omx_message::FILL_BUFFER_DONE:
80            {
81                msg->setPointer(
82                        "buffer", omx_msg.u.extended_buffer_data.buffer);
83                msg->setInt32(
84                        "range_offset",
85                        omx_msg.u.extended_buffer_data.range_offset);
86                msg->setInt32(
87                        "range_length",
88                        omx_msg.u.extended_buffer_data.range_length);
89                msg->setInt32(
90                        "flags",
91                        omx_msg.u.extended_buffer_data.flags);
92                msg->setInt64(
93                        "timestamp",
94                        omx_msg.u.extended_buffer_data.timestamp);
95                msg->setPointer(
96                        "platform_private",
97                        omx_msg.u.extended_buffer_data.platform_private);
98                msg->setPointer(
99                        "data_ptr",
100                        omx_msg.u.extended_buffer_data.data_ptr);
101                break;
102            }
103
104            default:
105                TRESPASS();
106                break;
107        }
108
109        msg->post();
110    }
111
112protected:
113    virtual ~CodecObserver() {}
114
115private:
116    sp<AMessage> mNotify;
117
118    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
119};
120
121////////////////////////////////////////////////////////////////////////////////
122
123struct ACodec::BaseState : public AState {
124    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
125
126protected:
127    enum PortMode {
128        KEEP_BUFFERS,
129        RESUBMIT_BUFFERS,
130        FREE_BUFFERS,
131    };
132
133    ACodec *mCodec;
134
135    virtual PortMode getPortMode(OMX_U32 portIndex);
136
137    virtual bool onMessageReceived(const sp<AMessage> &msg);
138
139    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
140
141    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
142    virtual void onInputBufferFilled(const sp<AMessage> &msg);
143
144    void postFillThisBuffer(BufferInfo *info);
145
146private:
147    bool onOMXMessage(const sp<AMessage> &msg);
148
149    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
150
151    bool onOMXFillBufferDone(
152            IOMX::buffer_id bufferID,
153            size_t rangeOffset, size_t rangeLength,
154            OMX_U32 flags,
155            int64_t timeUs,
156            void *platformPrivate,
157            void *dataPtr);
158
159    void getMoreInputDataIfPossible();
160
161    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
162};
163
164////////////////////////////////////////////////////////////////////////////////
165
166struct ACodec::UninitializedState : public ACodec::BaseState {
167    UninitializedState(ACodec *codec);
168
169protected:
170    virtual bool onMessageReceived(const sp<AMessage> &msg);
171
172private:
173    void onSetup(const sp<AMessage> &msg);
174
175    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
176};
177
178////////////////////////////////////////////////////////////////////////////////
179
180struct ACodec::LoadedToIdleState : public ACodec::BaseState {
181    LoadedToIdleState(ACodec *codec);
182
183protected:
184    virtual bool onMessageReceived(const sp<AMessage> &msg);
185    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
186    virtual void stateEntered();
187
188private:
189    status_t allocateBuffers();
190
191    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
192};
193
194////////////////////////////////////////////////////////////////////////////////
195
196struct ACodec::IdleToExecutingState : public ACodec::BaseState {
197    IdleToExecutingState(ACodec *codec);
198
199protected:
200    virtual bool onMessageReceived(const sp<AMessage> &msg);
201    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
202    virtual void stateEntered();
203
204private:
205    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
206};
207
208////////////////////////////////////////////////////////////////////////////////
209
210struct ACodec::ExecutingState : public ACodec::BaseState {
211    ExecutingState(ACodec *codec);
212
213    void submitOutputBuffers();
214
215    // Submit output buffers to the decoder, submit input buffers to client
216    // to fill with data.
217    void resume();
218
219    // Returns true iff input and output buffers are in play.
220    bool active() const { return mActive; }
221
222protected:
223    virtual PortMode getPortMode(OMX_U32 portIndex);
224    virtual bool onMessageReceived(const sp<AMessage> &msg);
225    virtual void stateEntered();
226
227    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
228
229private:
230    bool mActive;
231
232    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
233};
234
235////////////////////////////////////////////////////////////////////////////////
236
237struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
238    OutputPortSettingsChangedState(ACodec *codec);
239
240protected:
241    virtual PortMode getPortMode(OMX_U32 portIndex);
242    virtual bool onMessageReceived(const sp<AMessage> &msg);
243    virtual void stateEntered();
244
245    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
246
247private:
248    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
249};
250
251////////////////////////////////////////////////////////////////////////////////
252
253struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
254    ExecutingToIdleState(ACodec *codec);
255
256protected:
257    virtual bool onMessageReceived(const sp<AMessage> &msg);
258    virtual void stateEntered();
259
260    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
261
262    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
263    virtual void onInputBufferFilled(const sp<AMessage> &msg);
264
265private:
266    void changeStateIfWeOwnAllBuffers();
267
268    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
269};
270
271////////////////////////////////////////////////////////////////////////////////
272
273struct ACodec::IdleToLoadedState : public ACodec::BaseState {
274    IdleToLoadedState(ACodec *codec);
275
276protected:
277    virtual bool onMessageReceived(const sp<AMessage> &msg);
278    virtual void stateEntered();
279
280    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
281
282private:
283    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
284};
285
286////////////////////////////////////////////////////////////////////////////////
287
288struct ACodec::FlushingState : public ACodec::BaseState {
289    FlushingState(ACodec *codec);
290
291protected:
292    virtual bool onMessageReceived(const sp<AMessage> &msg);
293    virtual void stateEntered();
294
295    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
296
297    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
298    virtual void onInputBufferFilled(const sp<AMessage> &msg);
299
300private:
301    bool mFlushComplete[2];
302
303    void changeStateIfWeOwnAllBuffers();
304
305    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
306};
307
308////////////////////////////////////////////////////////////////////////////////
309
310ACodec::ACodec()
311    : mNode(NULL),
312      mSentFormat(false) {
313    mUninitializedState = new UninitializedState(this);
314    mLoadedToIdleState = new LoadedToIdleState(this);
315    mIdleToExecutingState = new IdleToExecutingState(this);
316    mExecutingState = new ExecutingState(this);
317
318    mOutputPortSettingsChangedState =
319        new OutputPortSettingsChangedState(this);
320
321    mExecutingToIdleState = new ExecutingToIdleState(this);
322    mIdleToLoadedState = new IdleToLoadedState(this);
323    mFlushingState = new FlushingState(this);
324
325    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
326    mInputEOSResult = OK;
327
328    changeState(mUninitializedState);
329}
330
331ACodec::~ACodec() {
332}
333
334void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
335    mNotify = msg;
336}
337
338void ACodec::initiateSetup(const sp<AMessage> &msg) {
339    msg->setWhat(kWhatSetup);
340    msg->setTarget(id());
341    msg->post();
342}
343
344void ACodec::signalFlush() {
345    (new AMessage(kWhatFlush, id()))->post();
346}
347
348void ACodec::signalResume() {
349    (new AMessage(kWhatResume, id()))->post();
350}
351
352void ACodec::initiateShutdown() {
353    (new AMessage(kWhatShutdown, id()))->post();
354}
355
356status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
357    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
358
359    CHECK(mDealer[portIndex] == NULL);
360    CHECK(mBuffers[portIndex].isEmpty());
361
362    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
363        return allocateOutputBuffersFromNativeWindow();
364    }
365
366    OMX_PARAM_PORTDEFINITIONTYPE def;
367    InitOMXParams(&def);
368    def.nPortIndex = portIndex;
369
370    status_t err = mOMX->getParameter(
371            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
372
373    if (err != OK) {
374        return err;
375    }
376
377    LOGV("[%s] Allocating %lu buffers of size %lu on %s port",
378            mComponentName.c_str(),
379            def.nBufferCountActual, def.nBufferSize,
380            portIndex == kPortIndexInput ? "input" : "output");
381
382    size_t totalSize = def.nBufferCountActual * def.nBufferSize;
383    mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
384
385    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
386        sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
387        CHECK(mem.get() != NULL);
388
389        IOMX::buffer_id buffer;
390
391        if (!strcasecmp(
392                    mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) {
393            if (portIndex == kPortIndexInput && i == 0) {
394                // Only log this warning once per allocation round.
395
396                LOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of "
397                     "OMX_AllocateBuffer instead of the preferred "
398                     "OMX_UseBuffer. Vendor must fix this.");
399            }
400
401            err = mOMX->allocateBufferWithBackup(
402                    mNode, portIndex, mem, &buffer);
403        } else {
404            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
405        }
406
407        if (err != OK) {
408            return err;
409        }
410
411        BufferInfo info;
412        info.mBufferID = buffer;
413        info.mStatus = BufferInfo::OWNED_BY_US;
414        info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
415        mBuffers[portIndex].push(info);
416    }
417
418    return OK;
419}
420
421status_t ACodec::allocateOutputBuffersFromNativeWindow() {
422    OMX_PARAM_PORTDEFINITIONTYPE def;
423    InitOMXParams(&def);
424    def.nPortIndex = kPortIndexOutput;
425
426    status_t err = mOMX->getParameter(
427            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
428
429    if (err != OK) {
430        return err;
431    }
432
433    err = native_window_set_scaling_mode(mNativeWindow.get(),
434            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
435
436    if (err != OK) {
437        return err;
438    }
439
440    err = native_window_set_buffers_geometry(
441            mNativeWindow.get(),
442            def.format.video.nFrameWidth,
443            def.format.video.nFrameHeight,
444            def.format.video.eColorFormat);
445
446    if (err != 0) {
447        LOGE("native_window_set_buffers_geometry failed: %s (%d)",
448                strerror(-err), -err);
449        return err;
450    }
451
452    // Set up the native window.
453    OMX_U32 usage = 0;
454    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
455    if (err != 0) {
456        LOGW("querying usage flags from OMX IL component failed: %d", err);
457        // XXX: Currently this error is logged, but not fatal.
458        usage = 0;
459    }
460
461    err = native_window_set_usage(
462            mNativeWindow.get(),
463            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
464
465    if (err != 0) {
466        LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
467        return err;
468    }
469
470    int minUndequeuedBufs = 0;
471    err = mNativeWindow->query(
472            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
473            &minUndequeuedBufs);
474
475    if (err != 0) {
476        LOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
477                strerror(-err), -err);
478        return err;
479    }
480
481    // XXX: Is this the right logic to use?  It's not clear to me what the OMX
482    // buffer counts refer to - how do they account for the renderer holding on
483    // to buffers?
484    if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
485        OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
486        def.nBufferCountActual = newBufferCount;
487        err = mOMX->setParameter(
488                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
489
490        if (err != OK) {
491            LOGE("[%s] setting nBufferCountActual to %lu failed: %d",
492                    mComponentName.c_str(), newBufferCount, err);
493            return err;
494        }
495    }
496
497    err = native_window_set_buffer_count(
498            mNativeWindow.get(), def.nBufferCountActual);
499
500    if (err != 0) {
501        LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
502                -err);
503        return err;
504    }
505
506    LOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
507         "output port",
508         mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
509
510    // Dequeue buffers and send them to OMX
511    for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
512        ANativeWindowBuffer *buf;
513        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
514        if (err != 0) {
515            LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
516            break;
517        }
518
519        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
520        BufferInfo info;
521        info.mStatus = BufferInfo::OWNED_BY_US;
522        info.mData = new ABuffer(0);
523        info.mGraphicBuffer = graphicBuffer;
524        mBuffers[kPortIndexOutput].push(info);
525
526        IOMX::buffer_id bufferId;
527        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
528                &bufferId);
529        if (err != 0) {
530            LOGE("registering GraphicBuffer %lu with OMX IL component failed: "
531                 "%d", i, err);
532            break;
533        }
534
535        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
536
537        LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
538             mComponentName.c_str(),
539             bufferId, graphicBuffer.get());
540    }
541
542    OMX_U32 cancelStart;
543    OMX_U32 cancelEnd;
544
545    if (err != 0) {
546        // If an error occurred while dequeuing we need to cancel any buffers
547        // that were dequeued.
548        cancelStart = 0;
549        cancelEnd = mBuffers[kPortIndexOutput].size();
550    } else {
551        // Return the last two buffers to the native window.
552        cancelStart = def.nBufferCountActual - minUndequeuedBufs;
553        cancelEnd = def.nBufferCountActual;
554    }
555
556    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
557        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
558        cancelBufferToNativeWindow(info);
559    }
560
561    return err;
562}
563
564status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
565    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
566
567    LOGV("[%s] Calling cancelBuffer on buffer %p",
568         mComponentName.c_str(), info->mBufferID);
569
570    int err = mNativeWindow->cancelBuffer(
571        mNativeWindow.get(), info->mGraphicBuffer.get());
572
573    CHECK_EQ(err, 0);
574
575    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
576
577    return OK;
578}
579
580ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
581    ANativeWindowBuffer *buf;
582    if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
583        LOGE("dequeueBuffer failed.");
584        return NULL;
585    }
586
587    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
588        BufferInfo *info =
589            &mBuffers[kPortIndexOutput].editItemAt(i);
590
591        if (info->mGraphicBuffer->handle == buf->handle) {
592            CHECK_EQ((int)info->mStatus,
593                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
594
595            info->mStatus = BufferInfo::OWNED_BY_US;
596
597            return info;
598        }
599    }
600
601    TRESPASS();
602
603    return NULL;
604}
605
606status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
607    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
608        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
609    }
610
611    mDealer[portIndex].clear();
612
613    return OK;
614}
615
616status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
617    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
618        BufferInfo *info =
619            &mBuffers[kPortIndexOutput].editItemAt(i);
620
621        if (info->mStatus !=
622                BufferInfo::OWNED_BY_COMPONENT) {
623            // We shouldn't have sent out any buffers to the client at this
624            // point.
625            CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
626
627            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
628        }
629    }
630
631    return OK;
632}
633
634status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
635    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
636
637    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
638            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
639
640    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
641            && info->mStatus == BufferInfo::OWNED_BY_US) {
642        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
643    }
644
645    CHECK_EQ(mOMX->freeBuffer(
646                mNode, portIndex, info->mBufferID),
647             (status_t)OK);
648
649    mBuffers[portIndex].removeAt(i);
650
651    return OK;
652}
653
654ACodec::BufferInfo *ACodec::findBufferByID(
655        uint32_t portIndex, IOMX::buffer_id bufferID,
656        ssize_t *index) {
657    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
658        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
659
660        if (info->mBufferID == bufferID) {
661            if (index != NULL) {
662                *index = i;
663            }
664            return info;
665        }
666    }
667
668    TRESPASS();
669
670    return NULL;
671}
672
673void ACodec::setComponentRole(
674        bool isEncoder, const char *mime) {
675    struct MimeToRole {
676        const char *mime;
677        const char *decoderRole;
678        const char *encoderRole;
679    };
680
681    static const MimeToRole kMimeToRole[] = {
682        { MEDIA_MIMETYPE_AUDIO_MPEG,
683            "audio_decoder.mp3", "audio_encoder.mp3" },
684        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
685            "audio_decoder.amrnb", "audio_encoder.amrnb" },
686        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
687            "audio_decoder.amrwb", "audio_encoder.amrwb" },
688        { MEDIA_MIMETYPE_AUDIO_AAC,
689            "audio_decoder.aac", "audio_encoder.aac" },
690        { MEDIA_MIMETYPE_VIDEO_AVC,
691            "video_decoder.avc", "video_encoder.avc" },
692        { MEDIA_MIMETYPE_VIDEO_MPEG4,
693            "video_decoder.mpeg4", "video_encoder.mpeg4" },
694        { MEDIA_MIMETYPE_VIDEO_H263,
695            "video_decoder.h263", "video_encoder.h263" },
696    };
697
698    static const size_t kNumMimeToRole =
699        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
700
701    size_t i;
702    for (i = 0; i < kNumMimeToRole; ++i) {
703        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
704            break;
705        }
706    }
707
708    if (i == kNumMimeToRole) {
709        return;
710    }
711
712    const char *role =
713        isEncoder ? kMimeToRole[i].encoderRole
714                  : kMimeToRole[i].decoderRole;
715
716    if (role != NULL) {
717        OMX_PARAM_COMPONENTROLETYPE roleParams;
718        InitOMXParams(&roleParams);
719
720        strncpy((char *)roleParams.cRole,
721                role, OMX_MAX_STRINGNAME_SIZE - 1);
722
723        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
724
725        status_t err = mOMX->setParameter(
726                mNode, OMX_IndexParamStandardComponentRole,
727                &roleParams, sizeof(roleParams));
728
729        if (err != OK) {
730            LOGW("[%s] Failed to set standard component role '%s'.",
731                 mComponentName.c_str(), role);
732        }
733    }
734}
735
736void ACodec::configureCodec(
737        const char *mime, const sp<AMessage> &msg) {
738    setComponentRole(false /* isEncoder */, mime);
739
740    if (!strncasecmp(mime, "video/", 6)) {
741        int32_t width, height;
742        CHECK(msg->findInt32("width", &width));
743        CHECK(msg->findInt32("height", &height));
744
745        CHECK_EQ(setupVideoDecoder(mime, width, height),
746                 (status_t)OK);
747    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
748        int32_t numChannels, sampleRate;
749        CHECK(msg->findInt32("channel-count", &numChannels));
750        CHECK(msg->findInt32("sample-rate", &sampleRate));
751
752        CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
753    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
754    } else {
755        TRESPASS();
756    }
757
758    int32_t maxInputSize;
759    if (msg->findInt32("max-input-size", &maxInputSize)) {
760        CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize),
761                 (status_t)OK);
762    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
763        CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192),  // XXX
764                 (status_t)OK);
765    }
766}
767
768status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
769    OMX_PARAM_PORTDEFINITIONTYPE def;
770    InitOMXParams(&def);
771    def.nPortIndex = portIndex;
772
773    status_t err = mOMX->getParameter(
774            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
775
776    if (err != OK) {
777        return err;
778    }
779
780    if (def.nBufferSize >= size) {
781        return OK;
782    }
783
784    def.nBufferSize = size;
785
786    err = mOMX->setParameter(
787            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
788
789    if (err != OK) {
790        return err;
791    }
792
793    err = mOMX->getParameter(
794            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
795
796    if (err != OK) {
797        return err;
798    }
799
800    CHECK(def.nBufferSize >= size);
801
802    return OK;
803}
804
805status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) {
806    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
807    InitOMXParams(&profile);
808    profile.nPortIndex = kPortIndexInput;
809
810    status_t err = mOMX->getParameter(
811            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
812
813    if (err != OK) {
814        return err;
815    }
816
817    profile.nChannels = numChannels;
818    profile.nSampleRate = sampleRate;
819    profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
820
821    err = mOMX->setParameter(
822            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
823
824    return err;
825}
826
827status_t ACodec::setVideoPortFormatType(
828        OMX_U32 portIndex,
829        OMX_VIDEO_CODINGTYPE compressionFormat,
830        OMX_COLOR_FORMATTYPE colorFormat) {
831    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
832    InitOMXParams(&format);
833    format.nPortIndex = portIndex;
834    format.nIndex = 0;
835    bool found = false;
836
837    OMX_U32 index = 0;
838    for (;;) {
839        format.nIndex = index;
840        status_t err = mOMX->getParameter(
841                mNode, OMX_IndexParamVideoPortFormat,
842                &format, sizeof(format));
843
844        if (err != OK) {
845            return err;
846        }
847
848        // The following assertion is violated by TI's video decoder.
849        // CHECK_EQ(format.nIndex, index);
850
851        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
852            if (portIndex == kPortIndexInput
853                    && colorFormat == format.eColorFormat) {
854                // eCompressionFormat does not seem right.
855                found = true;
856                break;
857            }
858            if (portIndex == kPortIndexOutput
859                    && compressionFormat == format.eCompressionFormat) {
860                // eColorFormat does not seem right.
861                found = true;
862                break;
863            }
864        }
865
866        if (format.eCompressionFormat == compressionFormat
867            && format.eColorFormat == colorFormat) {
868            found = true;
869            break;
870        }
871
872        ++index;
873    }
874
875    if (!found) {
876        return UNKNOWN_ERROR;
877    }
878
879    status_t err = mOMX->setParameter(
880            mNode, OMX_IndexParamVideoPortFormat,
881            &format, sizeof(format));
882
883    return err;
884}
885
886status_t ACodec::setSupportedOutputFormat() {
887    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
888    InitOMXParams(&format);
889    format.nPortIndex = kPortIndexOutput;
890    format.nIndex = 0;
891
892    status_t err = mOMX->getParameter(
893            mNode, OMX_IndexParamVideoPortFormat,
894            &format, sizeof(format));
895    CHECK_EQ(err, (status_t)OK);
896    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
897
898    CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
899           || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
900           || format.eColorFormat == OMX_COLOR_FormatCbYCrY
901           || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
902           || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
903
904    return mOMX->setParameter(
905            mNode, OMX_IndexParamVideoPortFormat,
906            &format, sizeof(format));
907}
908
909status_t ACodec::setupVideoDecoder(
910        const char *mime, int32_t width, int32_t height) {
911    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
912    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
913        compressionFormat = OMX_VIDEO_CodingAVC;
914    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
915        compressionFormat = OMX_VIDEO_CodingMPEG4;
916    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
917        compressionFormat = OMX_VIDEO_CodingH263;
918    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
919        compressionFormat = OMX_VIDEO_CodingMPEG2;
920    } else {
921        TRESPASS();
922    }
923
924    status_t err = setVideoPortFormatType(
925            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
926
927    if (err != OK) {
928        return err;
929    }
930
931    err = setSupportedOutputFormat();
932
933    if (err != OK) {
934        return err;
935    }
936
937    err = setVideoFormatOnPort(
938            kPortIndexInput, width, height, compressionFormat);
939
940    if (err != OK) {
941        return err;
942    }
943
944    err = setVideoFormatOnPort(
945            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
946
947    if (err != OK) {
948        return err;
949    }
950
951    return OK;
952}
953
954status_t ACodec::setVideoFormatOnPort(
955        OMX_U32 portIndex,
956        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
957    OMX_PARAM_PORTDEFINITIONTYPE def;
958    InitOMXParams(&def);
959    def.nPortIndex = portIndex;
960
961    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
962
963    status_t err = mOMX->getParameter(
964            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
965
966    CHECK_EQ(err, (status_t)OK);
967
968    if (portIndex == kPortIndexInput) {
969        // XXX Need a (much) better heuristic to compute input buffer sizes.
970        const size_t X = 64 * 1024;
971        if (def.nBufferSize < X) {
972            def.nBufferSize = X;
973        }
974    }
975
976    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
977
978    video_def->nFrameWidth = width;
979    video_def->nFrameHeight = height;
980
981    if (portIndex == kPortIndexInput) {
982        video_def->eCompressionFormat = compressionFormat;
983        video_def->eColorFormat = OMX_COLOR_FormatUnused;
984    }
985
986    err = mOMX->setParameter(
987            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
988
989    return err;
990}
991
992status_t ACodec::initNativeWindow() {
993    if (mNativeWindow != NULL) {
994        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
995    }
996
997    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
998    return OK;
999}
1000
1001bool ACodec::allYourBuffersAreBelongToUs(
1002        OMX_U32 portIndex) {
1003    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1004        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1005
1006        if (info->mStatus != BufferInfo::OWNED_BY_US
1007                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1008            LOGV("[%s] Buffer %p on port %ld still has status %d",
1009                    mComponentName.c_str(),
1010                    info->mBufferID, portIndex, info->mStatus);
1011            return false;
1012        }
1013    }
1014
1015    return true;
1016}
1017
1018bool ACodec::allYourBuffersAreBelongToUs() {
1019    return allYourBuffersAreBelongToUs(kPortIndexInput)
1020        && allYourBuffersAreBelongToUs(kPortIndexOutput);
1021}
1022
1023void ACodec::deferMessage(const sp<AMessage> &msg) {
1024    bool wasEmptyBefore = mDeferredQueue.empty();
1025    mDeferredQueue.push_back(msg);
1026}
1027
1028void ACodec::processDeferredMessages() {
1029    List<sp<AMessage> > queue = mDeferredQueue;
1030    mDeferredQueue.clear();
1031
1032    List<sp<AMessage> >::iterator it = queue.begin();
1033    while (it != queue.end()) {
1034        onMessageReceived(*it++);
1035    }
1036}
1037
1038void ACodec::sendFormatChange() {
1039    sp<AMessage> notify = mNotify->dup();
1040    notify->setInt32("what", kWhatOutputFormatChanged);
1041
1042    OMX_PARAM_PORTDEFINITIONTYPE def;
1043    InitOMXParams(&def);
1044    def.nPortIndex = kPortIndexOutput;
1045
1046    CHECK_EQ(mOMX->getParameter(
1047                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1048             (status_t)OK);
1049
1050    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1051
1052    switch (def.eDomain) {
1053        case OMX_PortDomainVideo:
1054        {
1055            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1056
1057            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1058            notify->setInt32("width", videoDef->nFrameWidth);
1059            notify->setInt32("height", videoDef->nFrameHeight);
1060
1061            OMX_CONFIG_RECTTYPE rect;
1062            InitOMXParams(&rect);
1063            rect.nPortIndex = kPortIndexOutput;
1064
1065            if (mOMX->getConfig(
1066                        mNode, OMX_IndexConfigCommonOutputCrop,
1067                        &rect, sizeof(rect)) != OK) {
1068                rect.nLeft = 0;
1069                rect.nTop = 0;
1070                rect.nWidth = videoDef->nFrameWidth;
1071                rect.nHeight = videoDef->nFrameHeight;
1072            }
1073
1074            CHECK_GE(rect.nLeft, 0);
1075            CHECK_GE(rect.nTop, 0);
1076            CHECK_GE(rect.nWidth, 0u);
1077            CHECK_GE(rect.nHeight, 0u);
1078            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1079            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1080
1081            notify->setRect(
1082                    "crop",
1083                    rect.nLeft,
1084                    rect.nTop,
1085                    rect.nLeft + rect.nWidth - 1,
1086                    rect.nTop + rect.nHeight - 1);
1087
1088            if (mNativeWindow != NULL) {
1089                android_native_rect_t crop;
1090                crop.left = rect.nLeft;
1091                crop.top = rect.nTop;
1092                crop.right = rect.nLeft + rect.nWidth;
1093                crop.bottom = rect.nTop + rect.nHeight;
1094
1095                CHECK_EQ(0, native_window_set_crop(
1096                            mNativeWindow.get(), &crop));
1097            }
1098            break;
1099        }
1100
1101        case OMX_PortDomainAudio:
1102        {
1103            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1104            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1105
1106            OMX_AUDIO_PARAM_PCMMODETYPE params;
1107            InitOMXParams(&params);
1108            params.nPortIndex = kPortIndexOutput;
1109
1110            CHECK_EQ(mOMX->getParameter(
1111                        mNode, OMX_IndexParamAudioPcm,
1112                        &params, sizeof(params)),
1113                     (status_t)OK);
1114
1115            CHECK(params.nChannels == 1 || params.bInterleaved);
1116            CHECK_EQ(params.nBitPerSample, 16u);
1117            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1118            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1119
1120            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1121            notify->setInt32("channel-count", params.nChannels);
1122            notify->setInt32("sample-rate", params.nSamplingRate);
1123            break;
1124        }
1125
1126        default:
1127            TRESPASS();
1128    }
1129
1130    notify->post();
1131
1132    mSentFormat = true;
1133}
1134
1135void ACodec::signalError(OMX_ERRORTYPE error) {
1136    sp<AMessage> notify = mNotify->dup();
1137    notify->setInt32("what", ACodec::kWhatError);
1138    notify->setInt32("omx-error", error);
1139    notify->post();
1140}
1141
1142////////////////////////////////////////////////////////////////////////////////
1143
1144ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1145    : AState(parentState),
1146      mCodec(codec) {
1147}
1148
1149ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1150    return KEEP_BUFFERS;
1151}
1152
1153bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1154    switch (msg->what()) {
1155        case kWhatInputBufferFilled:
1156        {
1157            onInputBufferFilled(msg);
1158            break;
1159        }
1160
1161        case kWhatOutputBufferDrained:
1162        {
1163            onOutputBufferDrained(msg);
1164            break;
1165        }
1166
1167        case ACodec::kWhatOMXMessage:
1168        {
1169            return onOMXMessage(msg);
1170        }
1171
1172        default:
1173            return false;
1174    }
1175
1176    return true;
1177}
1178
1179bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1180    int32_t type;
1181    CHECK(msg->findInt32("type", &type));
1182
1183    IOMX::node_id nodeID;
1184    CHECK(msg->findPointer("node", &nodeID));
1185    CHECK_EQ(nodeID, mCodec->mNode);
1186
1187    switch (type) {
1188        case omx_message::EVENT:
1189        {
1190            int32_t event, data1, data2;
1191            CHECK(msg->findInt32("event", &event));
1192            CHECK(msg->findInt32("data1", &data1));
1193            CHECK(msg->findInt32("data2", &data2));
1194
1195            if (event == OMX_EventCmdComplete
1196                    && data1 == OMX_CommandFlush
1197                    && data2 == (int32_t)OMX_ALL) {
1198                // Use of this notification is not consistent across
1199                // implementations. We'll drop this notification and rely
1200                // on flush-complete notifications on the individual port
1201                // indices instead.
1202
1203                return true;
1204            }
1205
1206            return onOMXEvent(
1207                    static_cast<OMX_EVENTTYPE>(event),
1208                    static_cast<OMX_U32>(data1),
1209                    static_cast<OMX_U32>(data2));
1210        }
1211
1212        case omx_message::EMPTY_BUFFER_DONE:
1213        {
1214            IOMX::buffer_id bufferID;
1215            CHECK(msg->findPointer("buffer", &bufferID));
1216
1217            return onOMXEmptyBufferDone(bufferID);
1218        }
1219
1220        case omx_message::FILL_BUFFER_DONE:
1221        {
1222            IOMX::buffer_id bufferID;
1223            CHECK(msg->findPointer("buffer", &bufferID));
1224
1225            int32_t rangeOffset, rangeLength, flags;
1226            int64_t timeUs;
1227            void *platformPrivate;
1228            void *dataPtr;
1229
1230            CHECK(msg->findInt32("range_offset", &rangeOffset));
1231            CHECK(msg->findInt32("range_length", &rangeLength));
1232            CHECK(msg->findInt32("flags", &flags));
1233            CHECK(msg->findInt64("timestamp", &timeUs));
1234            CHECK(msg->findPointer("platform_private", &platformPrivate));
1235            CHECK(msg->findPointer("data_ptr", &dataPtr));
1236
1237            return onOMXFillBufferDone(
1238                    bufferID,
1239                    (size_t)rangeOffset, (size_t)rangeLength,
1240                    (OMX_U32)flags,
1241                    timeUs,
1242                    platformPrivate,
1243                    dataPtr);
1244        }
1245
1246        default:
1247            TRESPASS();
1248            break;
1249    }
1250}
1251
1252bool ACodec::BaseState::onOMXEvent(
1253        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1254    if (event != OMX_EventError) {
1255        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
1256             mCodec->mComponentName.c_str(), event, data1, data2);
1257
1258        return false;
1259    }
1260
1261    LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
1262
1263    mCodec->signalError((OMX_ERRORTYPE)data1);
1264
1265    return true;
1266}
1267
1268bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
1269    LOGV("[%s] onOMXEmptyBufferDone %p",
1270         mCodec->mComponentName.c_str(), bufferID);
1271
1272    BufferInfo *info =
1273        mCodec->findBufferByID(kPortIndexInput, bufferID);
1274
1275    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1276    info->mStatus = BufferInfo::OWNED_BY_US;
1277
1278    PortMode mode = getPortMode(kPortIndexInput);
1279
1280    switch (mode) {
1281        case KEEP_BUFFERS:
1282            break;
1283
1284        case RESUBMIT_BUFFERS:
1285            postFillThisBuffer(info);
1286            break;
1287
1288        default:
1289        {
1290            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1291            TRESPASS();  // Not currently used
1292            break;
1293        }
1294    }
1295
1296    return true;
1297}
1298
1299void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1300    if (mCodec->mPortEOS[kPortIndexInput]) {
1301        return;
1302    }
1303
1304    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1305
1306    sp<AMessage> notify = mCodec->mNotify->dup();
1307    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1308    notify->setPointer("buffer-id", info->mBufferID);
1309
1310    info->mData->meta()->clear();
1311    notify->setObject("buffer", info->mData);
1312
1313    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1314    reply->setPointer("buffer-id", info->mBufferID);
1315
1316    notify->setMessage("reply", reply);
1317
1318    notify->post();
1319
1320    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1321}
1322
1323void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1324    IOMX::buffer_id bufferID;
1325    CHECK(msg->findPointer("buffer-id", &bufferID));
1326
1327    sp<RefBase> obj;
1328    int32_t err = OK;
1329    if (!msg->findObject("buffer", &obj)) {
1330        CHECK(msg->findInt32("err", &err));
1331
1332        LOGV("[%s] saw error %d instead of an input buffer",
1333             mCodec->mComponentName.c_str(), err);
1334
1335        obj.clear();
1336    }
1337
1338    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1339
1340    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1341    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1342
1343    info->mStatus = BufferInfo::OWNED_BY_US;
1344
1345    PortMode mode = getPortMode(kPortIndexInput);
1346
1347    switch (mode) {
1348        case KEEP_BUFFERS:
1349        {
1350            if (buffer == NULL) {
1351                if (!mCodec->mPortEOS[kPortIndexInput]) {
1352                    mCodec->mPortEOS[kPortIndexInput] = true;
1353                    mCodec->mInputEOSResult = err;
1354                }
1355            }
1356            break;
1357        }
1358
1359        case RESUBMIT_BUFFERS:
1360        {
1361            if (buffer != NULL) {
1362                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1363
1364                int64_t timeUs;
1365                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1366
1367                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1368
1369                int32_t isCSD;
1370                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1371                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1372                }
1373
1374                if (buffer != info->mData) {
1375                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1376                        LOGV("[%s] Needs to copy input data.",
1377                             mCodec->mComponentName.c_str());
1378                    }
1379
1380                    CHECK_LE(buffer->size(), info->mData->capacity());
1381                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1382                }
1383
1384                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
1385                    LOGV("[%s] calling emptyBuffer %p w/ codec specific data",
1386                         mCodec->mComponentName.c_str(), bufferID);
1387                } else {
1388                    LOGV("[%s] calling emptyBuffer %p w/ time %lld us",
1389                         mCodec->mComponentName.c_str(), bufferID, timeUs);
1390                }
1391
1392                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1393                            mCodec->mNode,
1394                            bufferID,
1395                            0,
1396                            buffer->size(),
1397                            flags,
1398                            timeUs),
1399                         (status_t)OK);
1400
1401                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1402
1403                getMoreInputDataIfPossible();
1404            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1405                if (err != ERROR_END_OF_STREAM) {
1406                    LOGV("[%s] Signalling EOS on the input port "
1407                         "due to error %d",
1408                         mCodec->mComponentName.c_str(), err);
1409                } else {
1410                    LOGV("[%s] Signalling EOS on the input port",
1411                         mCodec->mComponentName.c_str());
1412                }
1413
1414                LOGV("[%s] calling emptyBuffer %p signalling EOS",
1415                     mCodec->mComponentName.c_str(), bufferID);
1416
1417                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1418                            mCodec->mNode,
1419                            bufferID,
1420                            0,
1421                            0,
1422                            OMX_BUFFERFLAG_EOS,
1423                            0),
1424                         (status_t)OK);
1425
1426                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1427
1428                mCodec->mPortEOS[kPortIndexInput] = true;
1429                mCodec->mInputEOSResult = err;
1430            }
1431            break;
1432
1433            default:
1434                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1435                break;
1436        }
1437    }
1438}
1439
1440void ACodec::BaseState::getMoreInputDataIfPossible() {
1441    if (mCodec->mPortEOS[kPortIndexInput]) {
1442        return;
1443    }
1444
1445    BufferInfo *eligible = NULL;
1446
1447    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1448        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1449
1450#if 0
1451        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1452            // There's already a "read" pending.
1453            return;
1454        }
1455#endif
1456
1457        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1458            eligible = info;
1459        }
1460    }
1461
1462    if (eligible == NULL) {
1463        return;
1464    }
1465
1466    postFillThisBuffer(eligible);
1467}
1468
1469bool ACodec::BaseState::onOMXFillBufferDone(
1470        IOMX::buffer_id bufferID,
1471        size_t rangeOffset, size_t rangeLength,
1472        OMX_U32 flags,
1473        int64_t timeUs,
1474        void *platformPrivate,
1475        void *dataPtr) {
1476    LOGV("[%s] onOMXFillBufferDone %p time %lld us",
1477         mCodec->mComponentName.c_str(), bufferID, timeUs);
1478
1479    ssize_t index;
1480    BufferInfo *info =
1481        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1482
1483    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1484
1485    info->mStatus = BufferInfo::OWNED_BY_US;
1486
1487    PortMode mode = getPortMode(kPortIndexOutput);
1488
1489    switch (mode) {
1490        case KEEP_BUFFERS:
1491            break;
1492
1493        case RESUBMIT_BUFFERS:
1494        {
1495            if (rangeLength == 0) {
1496                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1497                    LOGV("[%s] calling fillBuffer %p",
1498                         mCodec->mComponentName.c_str(), info->mBufferID);
1499
1500                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1501                                mCodec->mNode, info->mBufferID),
1502                             (status_t)OK);
1503
1504                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1505                }
1506            } else {
1507                if (!mCodec->mSentFormat) {
1508                    mCodec->sendFormatChange();
1509                }
1510
1511                if (mCodec->mNativeWindow == NULL) {
1512                    info->mData->setRange(rangeOffset, rangeLength);
1513                }
1514
1515                info->mData->meta()->setInt64("timeUs", timeUs);
1516
1517                sp<AMessage> notify = mCodec->mNotify->dup();
1518                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1519                notify->setPointer("buffer-id", info->mBufferID);
1520                notify->setObject("buffer", info->mData);
1521
1522                sp<AMessage> reply =
1523                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1524
1525                reply->setPointer("buffer-id", info->mBufferID);
1526
1527                notify->setMessage("reply", reply);
1528
1529                notify->post();
1530
1531                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1532            }
1533
1534            if (flags & OMX_BUFFERFLAG_EOS) {
1535                sp<AMessage> notify = mCodec->mNotify->dup();
1536                notify->setInt32("what", ACodec::kWhatEOS);
1537                notify->setInt32("err", mCodec->mInputEOSResult);
1538                notify->post();
1539
1540                mCodec->mPortEOS[kPortIndexOutput] = true;
1541            }
1542            break;
1543        }
1544
1545        default:
1546        {
1547            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1548
1549            CHECK_EQ((status_t)OK,
1550                     mCodec->freeBuffer(kPortIndexOutput, index));
1551            break;
1552        }
1553    }
1554
1555    return true;
1556}
1557
1558void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1559    IOMX::buffer_id bufferID;
1560    CHECK(msg->findPointer("buffer-id", &bufferID));
1561
1562    ssize_t index;
1563    BufferInfo *info =
1564        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1565    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1566
1567    int32_t render;
1568    if (mCodec->mNativeWindow != NULL
1569            && msg->findInt32("render", &render) && render != 0) {
1570        // The client wants this buffer to be rendered.
1571
1572        if (mCodec->mNativeWindow->queueBuffer(
1573                    mCodec->mNativeWindow.get(),
1574                    info->mGraphicBuffer.get()) == OK) {
1575            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1576        } else {
1577            mCodec->signalError();
1578            info->mStatus = BufferInfo::OWNED_BY_US;
1579        }
1580    } else {
1581        info->mStatus = BufferInfo::OWNED_BY_US;
1582    }
1583
1584    PortMode mode = getPortMode(kPortIndexOutput);
1585
1586    switch (mode) {
1587        case KEEP_BUFFERS:
1588        {
1589            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1590
1591            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1592                // We cannot resubmit the buffer we just rendered, dequeue
1593                // the spare instead.
1594
1595                info = mCodec->dequeueBufferFromNativeWindow();
1596            }
1597            break;
1598        }
1599
1600        case RESUBMIT_BUFFERS:
1601        {
1602            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1603                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1604                    // We cannot resubmit the buffer we just rendered, dequeue
1605                    // the spare instead.
1606
1607                    info = mCodec->dequeueBufferFromNativeWindow();
1608                }
1609
1610                if (info != NULL) {
1611                    LOGV("[%s] calling fillBuffer %p",
1612                         mCodec->mComponentName.c_str(), info->mBufferID);
1613
1614                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1615                             (status_t)OK);
1616
1617                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1618                }
1619            }
1620            break;
1621        }
1622
1623        default:
1624        {
1625            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1626
1627            CHECK_EQ((status_t)OK,
1628                     mCodec->freeBuffer(kPortIndexOutput, index));
1629            break;
1630        }
1631    }
1632}
1633
1634////////////////////////////////////////////////////////////////////////////////
1635
1636ACodec::UninitializedState::UninitializedState(ACodec *codec)
1637    : BaseState(codec) {
1638}
1639
1640bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1641    bool handled = false;
1642
1643    switch (msg->what()) {
1644        case ACodec::kWhatSetup:
1645        {
1646            onSetup(msg);
1647
1648            handled = true;
1649            break;
1650        }
1651
1652        case ACodec::kWhatShutdown:
1653        {
1654            sp<AMessage> notify = mCodec->mNotify->dup();
1655            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1656            notify->post();
1657
1658            handled = true;
1659            break;
1660        }
1661
1662        case ACodec::kWhatFlush:
1663        {
1664            sp<AMessage> notify = mCodec->mNotify->dup();
1665            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1666            notify->post();
1667
1668            handled = true;
1669            break;
1670        }
1671
1672        default:
1673            return BaseState::onMessageReceived(msg);
1674    }
1675
1676    return handled;
1677}
1678
1679void ACodec::UninitializedState::onSetup(
1680        const sp<AMessage> &msg) {
1681    OMXClient client;
1682    CHECK_EQ(client.connect(), (status_t)OK);
1683
1684    sp<IOMX> omx = client.interface();
1685
1686    AString mime;
1687    CHECK(msg->findString("mime", &mime));
1688
1689    Vector<String8> matchingCodecs;
1690    OMXCodec::findMatchingCodecs(
1691            mime.c_str(),
1692            false, // createEncoder
1693            NULL,  // matchComponentName
1694            0,     // flags
1695            &matchingCodecs);
1696
1697    sp<CodecObserver> observer = new CodecObserver;
1698    IOMX::node_id node = NULL;
1699
1700    AString componentName;
1701
1702    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
1703            ++matchIndex) {
1704        componentName = matchingCodecs.itemAt(matchIndex).string();
1705
1706        pid_t tid = androidGetTid();
1707        int prevPriority = androidGetThreadPriority(tid);
1708        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
1709        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
1710        androidSetThreadPriority(tid, prevPriority);
1711
1712        if (err == OK) {
1713            break;
1714        }
1715
1716        node = NULL;
1717    }
1718
1719    if (node == NULL) {
1720        LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str());
1721
1722        mCodec->signalError(OMX_ErrorComponentNotFound);
1723        return;
1724    }
1725
1726    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1727    observer->setNotificationMessage(notify);
1728
1729    mCodec->mComponentName = componentName;
1730    mCodec->mOMX = omx;
1731    mCodec->mNode = node;
1732
1733    mCodec->mPortEOS[kPortIndexInput] =
1734        mCodec->mPortEOS[kPortIndexOutput] = false;
1735
1736    mCodec->mInputEOSResult = OK;
1737
1738    mCodec->configureCodec(mime.c_str(), msg);
1739
1740    sp<RefBase> obj;
1741    if (msg->findObject("native-window", &obj)
1742            && strncmp("OMX.google.", componentName.c_str(), 11)) {
1743        sp<NativeWindowWrapper> nativeWindow(
1744                static_cast<NativeWindowWrapper *>(obj.get()));
1745        CHECK(nativeWindow != NULL);
1746        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
1747    }
1748
1749    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1750
1751    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1752             (status_t)OK);
1753
1754    mCodec->changeState(mCodec->mLoadedToIdleState);
1755}
1756
1757////////////////////////////////////////////////////////////////////////////////
1758
1759ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1760    : BaseState(codec) {
1761}
1762
1763void ACodec::LoadedToIdleState::stateEntered() {
1764    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1765
1766    status_t err;
1767    if ((err = allocateBuffers()) != OK) {
1768        LOGE("Failed to allocate buffers after transitioning to IDLE state "
1769             "(error 0x%08x)",
1770             err);
1771
1772        mCodec->signalError();
1773    }
1774}
1775
1776status_t ACodec::LoadedToIdleState::allocateBuffers() {
1777    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1778
1779    if (err != OK) {
1780        return err;
1781    }
1782
1783    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1784}
1785
1786bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1787    switch (msg->what()) {
1788        case kWhatShutdown:
1789        {
1790            mCodec->deferMessage(msg);
1791            return true;
1792        }
1793
1794        default:
1795            return BaseState::onMessageReceived(msg);
1796    }
1797}
1798
1799bool ACodec::LoadedToIdleState::onOMXEvent(
1800        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1801    switch (event) {
1802        case OMX_EventCmdComplete:
1803        {
1804            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1805            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1806
1807            CHECK_EQ(mCodec->mOMX->sendCommand(
1808                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1809                     (status_t)OK);
1810
1811            mCodec->changeState(mCodec->mIdleToExecutingState);
1812
1813            return true;
1814        }
1815
1816        default:
1817            return BaseState::onOMXEvent(event, data1, data2);
1818    }
1819}
1820
1821////////////////////////////////////////////////////////////////////////////////
1822
1823ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1824    : BaseState(codec) {
1825}
1826
1827void ACodec::IdleToExecutingState::stateEntered() {
1828    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1829}
1830
1831bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1832    switch (msg->what()) {
1833        case kWhatShutdown:
1834        {
1835            mCodec->deferMessage(msg);
1836            return true;
1837        }
1838
1839        default:
1840            return BaseState::onMessageReceived(msg);
1841    }
1842}
1843
1844bool ACodec::IdleToExecutingState::onOMXEvent(
1845        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1846    switch (event) {
1847        case OMX_EventCmdComplete:
1848        {
1849            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1850            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1851
1852            mCodec->mExecutingState->resume();
1853            mCodec->changeState(mCodec->mExecutingState);
1854
1855            return true;
1856        }
1857
1858        default:
1859            return BaseState::onOMXEvent(event, data1, data2);
1860    }
1861}
1862
1863////////////////////////////////////////////////////////////////////////////////
1864
1865ACodec::ExecutingState::ExecutingState(ACodec *codec)
1866    : BaseState(codec),
1867      mActive(false) {
1868}
1869
1870ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1871        OMX_U32 portIndex) {
1872    return RESUBMIT_BUFFERS;
1873}
1874
1875void ACodec::ExecutingState::submitOutputBuffers() {
1876    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1877        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1878
1879        if (mCodec->mNativeWindow != NULL) {
1880            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1881                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1882
1883            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1884                continue;
1885            }
1886
1887            status_t err = mCodec->mNativeWindow->lockBuffer(
1888                    mCodec->mNativeWindow.get(),
1889                    info->mGraphicBuffer.get());
1890            CHECK_EQ(err, (status_t)OK);
1891        } else {
1892            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1893        }
1894
1895        LOGV("[%s] calling fillBuffer %p",
1896             mCodec->mComponentName.c_str(), info->mBufferID);
1897
1898        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1899                 (status_t)OK);
1900
1901        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1902    }
1903}
1904
1905void ACodec::ExecutingState::resume() {
1906    if (mActive) {
1907        LOGV("[%s] We're already active, no need to resume.",
1908             mCodec->mComponentName.c_str());
1909
1910        return;
1911    }
1912
1913    submitOutputBuffers();
1914
1915    // Post the first input buffer.
1916    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1917    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1918
1919    postFillThisBuffer(info);
1920
1921    mActive = true;
1922}
1923
1924void ACodec::ExecutingState::stateEntered() {
1925    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
1926
1927    mCodec->processDeferredMessages();
1928}
1929
1930bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1931    bool handled = false;
1932
1933    switch (msg->what()) {
1934        case kWhatShutdown:
1935        {
1936            mActive = false;
1937
1938            CHECK_EQ(mCodec->mOMX->sendCommand(
1939                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1940                     (status_t)OK);
1941
1942            mCodec->changeState(mCodec->mExecutingToIdleState);
1943
1944            handled = true;
1945            break;
1946        }
1947
1948        case kWhatFlush:
1949        {
1950            mActive = false;
1951
1952            CHECK_EQ(mCodec->mOMX->sendCommand(
1953                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1954                     (status_t)OK);
1955
1956            mCodec->changeState(mCodec->mFlushingState);
1957
1958            handled = true;
1959            break;
1960        }
1961
1962        case kWhatResume:
1963        {
1964            resume();
1965
1966            handled = true;
1967            break;
1968        }
1969
1970        default:
1971            handled = BaseState::onMessageReceived(msg);
1972            break;
1973    }
1974
1975    return handled;
1976}
1977
1978bool ACodec::ExecutingState::onOMXEvent(
1979        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1980    switch (event) {
1981        case OMX_EventPortSettingsChanged:
1982        {
1983            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1984
1985            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
1986                CHECK_EQ(mCodec->mOMX->sendCommand(
1987                            mCodec->mNode,
1988                            OMX_CommandPortDisable, kPortIndexOutput),
1989                         (status_t)OK);
1990
1991                mCodec->freeOutputBuffersNotOwnedByComponent();
1992
1993                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1994            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1995                mCodec->mSentFormat = false;
1996            } else {
1997                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1998                     mCodec->mComponentName.c_str(), data2);
1999            }
2000
2001            return true;
2002        }
2003
2004        case OMX_EventBufferFlag:
2005        {
2006            return true;
2007        }
2008
2009        default:
2010            return BaseState::onOMXEvent(event, data1, data2);
2011    }
2012}
2013
2014////////////////////////////////////////////////////////////////////////////////
2015
2016ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
2017        ACodec *codec)
2018    : BaseState(codec) {
2019}
2020
2021ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
2022        OMX_U32 portIndex) {
2023    if (portIndex == kPortIndexOutput) {
2024        return FREE_BUFFERS;
2025    }
2026
2027    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
2028
2029    return RESUBMIT_BUFFERS;
2030}
2031
2032bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
2033        const sp<AMessage> &msg) {
2034    bool handled = false;
2035
2036    switch (msg->what()) {
2037        case kWhatFlush:
2038        case kWhatShutdown:
2039        case kWhatResume:
2040        {
2041            if (msg->what() == kWhatResume) {
2042                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
2043            }
2044
2045            mCodec->deferMessage(msg);
2046            handled = true;
2047            break;
2048        }
2049
2050        default:
2051            handled = BaseState::onMessageReceived(msg);
2052            break;
2053    }
2054
2055    return handled;
2056}
2057
2058void ACodec::OutputPortSettingsChangedState::stateEntered() {
2059    LOGV("[%s] Now handling output port settings change",
2060         mCodec->mComponentName.c_str());
2061}
2062
2063bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
2064        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2065    switch (event) {
2066        case OMX_EventCmdComplete:
2067        {
2068            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
2069                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2070
2071                LOGV("[%s] Output port now disabled.",
2072                        mCodec->mComponentName.c_str());
2073
2074                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
2075                mCodec->mDealer[kPortIndexOutput].clear();
2076
2077                CHECK_EQ(mCodec->mOMX->sendCommand(
2078                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
2079                         (status_t)OK);
2080
2081                status_t err;
2082                if ((err = mCodec->allocateBuffersOnPort(
2083                                kPortIndexOutput)) != OK) {
2084                    LOGE("Failed to allocate output port buffers after "
2085                         "port reconfiguration (error 0x%08x)",
2086                         err);
2087
2088                    mCodec->signalError();
2089                }
2090
2091                return true;
2092            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
2093                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2094
2095                mCodec->mSentFormat = false;
2096
2097                LOGV("[%s] Output port now reenabled.",
2098                        mCodec->mComponentName.c_str());
2099
2100                if (mCodec->mExecutingState->active()) {
2101                    mCodec->mExecutingState->submitOutputBuffers();
2102                }
2103
2104                mCodec->changeState(mCodec->mExecutingState);
2105
2106                return true;
2107            }
2108
2109            return false;
2110        }
2111
2112        default:
2113            return false;
2114    }
2115}
2116
2117////////////////////////////////////////////////////////////////////////////////
2118
2119ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2120    : BaseState(codec) {
2121}
2122
2123bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2124    bool handled = false;
2125
2126    switch (msg->what()) {
2127        case kWhatFlush:
2128        {
2129            // Don't send me a flush request if you previously wanted me
2130            // to shutdown.
2131            TRESPASS();
2132            break;
2133        }
2134
2135        case kWhatShutdown:
2136        {
2137            // We're already doing that...
2138
2139            handled = true;
2140            break;
2141        }
2142
2143        default:
2144            handled = BaseState::onMessageReceived(msg);
2145            break;
2146    }
2147
2148    return handled;
2149}
2150
2151void ACodec::ExecutingToIdleState::stateEntered() {
2152    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2153
2154    mCodec->mSentFormat = false;
2155}
2156
2157bool ACodec::ExecutingToIdleState::onOMXEvent(
2158        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2159    switch (event) {
2160        case OMX_EventCmdComplete:
2161        {
2162            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2163            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2164
2165            changeStateIfWeOwnAllBuffers();
2166
2167            return true;
2168        }
2169
2170        case OMX_EventPortSettingsChanged:
2171        case OMX_EventBufferFlag:
2172        {
2173            // We're shutting down and don't care about this anymore.
2174            return true;
2175        }
2176
2177        default:
2178            return BaseState::onOMXEvent(event, data1, data2);
2179    }
2180}
2181
2182void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2183    if (mCodec->allYourBuffersAreBelongToUs()) {
2184        CHECK_EQ(mCodec->mOMX->sendCommand(
2185                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2186                 (status_t)OK);
2187
2188        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2189        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2190
2191        mCodec->changeState(mCodec->mIdleToLoadedState);
2192    }
2193}
2194
2195void ACodec::ExecutingToIdleState::onInputBufferFilled(
2196        const sp<AMessage> &msg) {
2197    BaseState::onInputBufferFilled(msg);
2198
2199    changeStateIfWeOwnAllBuffers();
2200}
2201
2202void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2203        const sp<AMessage> &msg) {
2204    BaseState::onOutputBufferDrained(msg);
2205
2206    changeStateIfWeOwnAllBuffers();
2207}
2208
2209////////////////////////////////////////////////////////////////////////////////
2210
2211ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2212    : BaseState(codec) {
2213}
2214
2215bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2216    bool handled = false;
2217
2218    switch (msg->what()) {
2219        case kWhatShutdown:
2220        {
2221            // We're already doing that...
2222
2223            handled = true;
2224            break;
2225        }
2226
2227        case kWhatFlush:
2228        {
2229            // Don't send me a flush request if you previously wanted me
2230            // to shutdown.
2231            TRESPASS();
2232            break;
2233        }
2234
2235        default:
2236            handled = BaseState::onMessageReceived(msg);
2237            break;
2238    }
2239
2240    return handled;
2241}
2242
2243void ACodec::IdleToLoadedState::stateEntered() {
2244    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2245}
2246
2247bool ACodec::IdleToLoadedState::onOMXEvent(
2248        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2249    switch (event) {
2250        case OMX_EventCmdComplete:
2251        {
2252            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2253            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2254
2255            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2256
2257            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2258
2259            mCodec->mNativeWindow.clear();
2260            mCodec->mNode = NULL;
2261            mCodec->mOMX.clear();
2262            mCodec->mComponentName.clear();
2263
2264            mCodec->changeState(mCodec->mUninitializedState);
2265
2266            sp<AMessage> notify = mCodec->mNotify->dup();
2267            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2268            notify->post();
2269
2270            return true;
2271        }
2272
2273        default:
2274            return BaseState::onOMXEvent(event, data1, data2);
2275    }
2276}
2277
2278////////////////////////////////////////////////////////////////////////////////
2279
2280ACodec::FlushingState::FlushingState(ACodec *codec)
2281    : BaseState(codec) {
2282}
2283
2284void ACodec::FlushingState::stateEntered() {
2285    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2286
2287    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2288}
2289
2290bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2291    bool handled = false;
2292
2293    switch (msg->what()) {
2294        case kWhatShutdown:
2295        {
2296            mCodec->deferMessage(msg);
2297            break;
2298        }
2299
2300        case kWhatFlush:
2301        {
2302            // We're already doing this right now.
2303            handled = true;
2304            break;
2305        }
2306
2307        default:
2308            handled = BaseState::onMessageReceived(msg);
2309            break;
2310    }
2311
2312    return handled;
2313}
2314
2315bool ACodec::FlushingState::onOMXEvent(
2316        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2317    switch (event) {
2318        case OMX_EventCmdComplete:
2319        {
2320            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2321
2322            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2323                CHECK(!mFlushComplete[data2]);
2324                mFlushComplete[data2] = true;
2325
2326                if (mFlushComplete[kPortIndexInput]
2327                        && mFlushComplete[kPortIndexOutput]) {
2328                    changeStateIfWeOwnAllBuffers();
2329                }
2330            } else {
2331                CHECK_EQ(data2, OMX_ALL);
2332                CHECK(mFlushComplete[kPortIndexInput]);
2333                CHECK(mFlushComplete[kPortIndexOutput]);
2334
2335                changeStateIfWeOwnAllBuffers();
2336            }
2337
2338            return true;
2339        }
2340
2341        case OMX_EventPortSettingsChanged:
2342        {
2343            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2344            msg->setInt32("type", omx_message::EVENT);
2345            msg->setPointer("node", mCodec->mNode);
2346            msg->setInt32("event", event);
2347            msg->setInt32("data1", data1);
2348            msg->setInt32("data2", data2);
2349
2350            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2351                 mCodec->mComponentName.c_str());
2352
2353            mCodec->deferMessage(msg);
2354
2355            return true;
2356        }
2357
2358        default:
2359            return BaseState::onOMXEvent(event, data1, data2);
2360    }
2361
2362    return true;
2363}
2364
2365void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2366    BaseState::onOutputBufferDrained(msg);
2367
2368    changeStateIfWeOwnAllBuffers();
2369}
2370
2371void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2372    BaseState::onInputBufferFilled(msg);
2373
2374    changeStateIfWeOwnAllBuffers();
2375}
2376
2377void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2378    if (mFlushComplete[kPortIndexInput]
2379            && mFlushComplete[kPortIndexOutput]
2380            && mCodec->allYourBuffersAreBelongToUs()) {
2381        sp<AMessage> notify = mCodec->mNotify->dup();
2382        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2383        notify->post();
2384
2385        mCodec->mPortEOS[kPortIndexInput] =
2386            mCodec->mPortEOS[kPortIndexOutput] = false;
2387
2388        mCodec->mInputEOSResult = OK;
2389
2390        mCodec->changeState(mCodec->mExecutingState);
2391    }
2392}
2393
2394}  // namespace android
2395