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