MediaCodec.cpp revision 2d8bedd05437b6fccdbc6bf70f673ffd86744d59
1/*
2 * Copyright 2012, 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 "MediaCodec"
19#include <utils/Log.h>
20
21#include <media/stagefright/MediaCodec.h>
22
23#include "include/SoftwareRenderer.h"
24
25#include <gui/SurfaceTextureClient.h>
26#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
29#include <media/stagefright/ACodec.h>
30#include <media/stagefright/MediaErrors.h>
31#include <media/stagefright/MetaData.h>
32#include <media/stagefright/NativeWindowWrapper.h>
33
34namespace android {
35
36// static
37sp<MediaCodec> MediaCodec::CreateByType(
38        const sp<ALooper> &looper, const char *mime, bool encoder) {
39    sp<MediaCodec> codec = new MediaCodec(looper);
40    if (codec->init(mime, true /* nameIsType */, encoder) != OK) {
41        return NULL;
42    }
43
44    return codec;
45}
46
47// static
48sp<MediaCodec> MediaCodec::CreateByComponentName(
49        const sp<ALooper> &looper, const char *name) {
50    sp<MediaCodec> codec = new MediaCodec(looper);
51    if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) {
52        return NULL;
53    }
54
55    return codec;
56}
57
58MediaCodec::MediaCodec(const sp<ALooper> &looper)
59    : mState(UNINITIALIZED),
60      mLooper(looper),
61      mCodec(new ACodec),
62      mFlags(0),
63      mSoftRenderer(NULL),
64      mDequeueInputTimeoutGeneration(0),
65      mDequeueInputReplyID(0),
66      mDequeueOutputTimeoutGeneration(0),
67      mDequeueOutputReplyID(0) {
68}
69
70MediaCodec::~MediaCodec() {
71    CHECK_EQ(mState, UNINITIALIZED);
72}
73
74// static
75status_t MediaCodec::PostAndAwaitResponse(
76        const sp<AMessage> &msg, sp<AMessage> *response) {
77    status_t err = msg->postAndAwaitResponse(response);
78
79    if (err != OK) {
80        return err;
81    }
82
83    if (!(*response)->findInt32("err", &err)) {
84        err = OK;
85    }
86
87    return err;
88}
89
90status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
91    // Current video decoders do not return from OMX_FillThisBuffer
92    // quickly, violating the OpenMAX specs, until that is remedied
93    // we need to invest in an extra looper to free the main event
94    // queue.
95    bool needDedicatedLooper = false;
96    if (nameIsType && !strncasecmp(name, "video/", 6)) {
97        needDedicatedLooper = true;
98    } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) {
99        needDedicatedLooper = true;
100    }
101
102    if (needDedicatedLooper) {
103        if (mCodecLooper == NULL) {
104            mCodecLooper = new ALooper;
105            mCodecLooper->setName("CodecLooper");
106            mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
107        }
108
109        mCodecLooper->registerHandler(mCodec);
110    } else {
111        mLooper->registerHandler(mCodec);
112    }
113
114    mLooper->registerHandler(this);
115
116    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
117
118    sp<AMessage> msg = new AMessage(kWhatInit, id());
119    msg->setString("name", name);
120    msg->setInt32("nameIsType", nameIsType);
121
122    if (nameIsType) {
123        msg->setInt32("encoder", encoder);
124    }
125
126    sp<AMessage> response;
127    return PostAndAwaitResponse(msg, &response);
128}
129
130status_t MediaCodec::configure(
131        const sp<AMessage> &format,
132        const sp<SurfaceTextureClient> &nativeWindow,
133        uint32_t flags) {
134    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
135
136    msg->setMessage("format", format);
137    msg->setInt32("flags", flags);
138
139    if (nativeWindow != NULL) {
140        if (!(mFlags & kFlagIsSoftwareCodec)) {
141            msg->setObject(
142                    "native-window",
143                    new NativeWindowWrapper(nativeWindow));
144        } else {
145            mNativeWindow = nativeWindow;
146        }
147    }
148
149    sp<AMessage> response;
150    return PostAndAwaitResponse(msg, &response);
151}
152
153status_t MediaCodec::start() {
154    sp<AMessage> msg = new AMessage(kWhatStart, id());
155
156    sp<AMessage> response;
157    return PostAndAwaitResponse(msg, &response);
158}
159
160status_t MediaCodec::stop() {
161    sp<AMessage> msg = new AMessage(kWhatStop, id());
162
163    sp<AMessage> response;
164    return PostAndAwaitResponse(msg, &response);
165}
166
167status_t MediaCodec::queueInputBuffer(
168        size_t index,
169        size_t offset,
170        size_t size,
171        int64_t presentationTimeUs,
172        uint32_t flags) {
173    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
174    msg->setSize("index", index);
175    msg->setSize("offset", offset);
176    msg->setSize("size", size);
177    msg->setInt64("timeUs", presentationTimeUs);
178    msg->setInt32("flags", flags);
179
180    sp<AMessage> response;
181    return PostAndAwaitResponse(msg, &response);
182}
183
184status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
185    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
186    msg->setInt64("timeoutUs", timeoutUs);
187
188    sp<AMessage> response;
189    status_t err;
190    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
191        return err;
192    }
193
194    CHECK(response->findSize("index", index));
195
196    return OK;
197}
198
199status_t MediaCodec::dequeueOutputBuffer(
200        size_t *index,
201        size_t *offset,
202        size_t *size,
203        int64_t *presentationTimeUs,
204        uint32_t *flags,
205        int64_t timeoutUs) {
206    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
207    msg->setInt64("timeoutUs", timeoutUs);
208
209    sp<AMessage> response;
210    status_t err;
211    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
212        return err;
213    }
214
215    CHECK(response->findSize("index", index));
216    CHECK(response->findSize("offset", offset));
217    CHECK(response->findSize("size", size));
218    CHECK(response->findInt64("timeUs", presentationTimeUs));
219    CHECK(response->findInt32("flags", (int32_t *)flags));
220
221    return OK;
222}
223
224status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
225    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
226    msg->setSize("index", index);
227    msg->setInt32("render", true);
228
229    sp<AMessage> response;
230    return PostAndAwaitResponse(msg, &response);
231}
232
233status_t MediaCodec::releaseOutputBuffer(size_t index) {
234    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
235    msg->setSize("index", index);
236
237    sp<AMessage> response;
238    return PostAndAwaitResponse(msg, &response);
239}
240
241status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
242    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
243
244    sp<AMessage> response;
245    status_t err;
246    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
247        return err;
248    }
249
250    CHECK(response->findMessage("format", format));
251
252    return OK;
253}
254
255status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
256    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
257    msg->setInt32("portIndex", kPortIndexInput);
258    msg->setPointer("buffers", buffers);
259
260    sp<AMessage> response;
261    return PostAndAwaitResponse(msg, &response);
262}
263
264status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
265    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
266    msg->setInt32("portIndex", kPortIndexOutput);
267    msg->setPointer("buffers", buffers);
268
269    sp<AMessage> response;
270    return PostAndAwaitResponse(msg, &response);
271}
272
273status_t MediaCodec::flush() {
274    sp<AMessage> msg = new AMessage(kWhatFlush, id());
275
276    sp<AMessage> response;
277    return PostAndAwaitResponse(msg, &response);
278}
279
280////////////////////////////////////////////////////////////////////////////////
281
282void MediaCodec::cancelPendingDequeueOperations() {
283    if (mFlags & kFlagDequeueInputPending) {
284        sp<AMessage> response = new AMessage;
285        response->setInt32("err", INVALID_OPERATION);
286        response->postReply(mDequeueInputReplyID);
287
288        ++mDequeueInputTimeoutGeneration;
289        mDequeueInputReplyID = 0;
290        mFlags &= ~kFlagDequeueInputPending;
291    }
292
293    if (mFlags & kFlagDequeueOutputPending) {
294        sp<AMessage> response = new AMessage;
295        response->setInt32("err", INVALID_OPERATION);
296        response->postReply(mDequeueOutputReplyID);
297
298        ++mDequeueOutputTimeoutGeneration;
299        mDequeueOutputReplyID = 0;
300        mFlags &= ~kFlagDequeueOutputPending;
301    }
302}
303
304bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
305    if (mState != STARTED
306            || (mFlags & kFlagStickyError)
307            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
308        sp<AMessage> response = new AMessage;
309        response->setInt32("err", INVALID_OPERATION);
310
311        response->postReply(replyID);
312
313        return true;
314    }
315
316    ssize_t index = dequeuePortBuffer(kPortIndexInput);
317
318    if (index < 0) {
319        CHECK_EQ(index, -EAGAIN);
320        return false;
321    }
322
323    sp<AMessage> response = new AMessage;
324    response->setSize("index", index);
325    response->postReply(replyID);
326
327    return true;
328}
329
330bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
331    sp<AMessage> response = new AMessage;
332
333    if (mState != STARTED
334            || (mFlags & kFlagStickyError)
335            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
336        response->setInt32("err", INVALID_OPERATION);
337    } else if (mFlags & kFlagOutputBuffersChanged) {
338        response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
339        mFlags &= ~kFlagOutputBuffersChanged;
340    } else if (mFlags & kFlagOutputFormatChanged) {
341        response->setInt32("err", INFO_FORMAT_CHANGED);
342        mFlags &= ~kFlagOutputFormatChanged;
343    } else {
344        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
345
346        if (index < 0) {
347            CHECK_EQ(index, -EAGAIN);
348            return false;
349        }
350
351        const sp<ABuffer> &buffer =
352            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
353
354        response->setSize("index", index);
355        response->setSize("offset", buffer->offset());
356        response->setSize("size", buffer->size());
357
358        int64_t timeUs;
359        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
360
361        response->setInt64("timeUs", timeUs);
362
363        int32_t omxFlags;
364        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
365
366        uint32_t flags = 0;
367        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
368            flags |= BUFFER_FLAG_SYNCFRAME;
369        }
370        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
371            flags |= BUFFER_FLAG_CODECCONFIG;
372        }
373        if (omxFlags & OMX_BUFFERFLAG_EOS) {
374            flags |= BUFFER_FLAG_EOS;
375        }
376
377        response->setInt32("flags", flags);
378    }
379
380    response->postReply(replyID);
381
382    return true;
383}
384
385void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
386    switch (msg->what()) {
387        case kWhatCodecNotify:
388        {
389            int32_t what;
390            CHECK(msg->findInt32("what", &what));
391
392            switch (what) {
393                case ACodec::kWhatError:
394                {
395                    int32_t omxError, internalError;
396                    CHECK(msg->findInt32("omx-error", &omxError));
397                    CHECK(msg->findInt32("err", &internalError));
398
399                    ALOGE("Codec reported an error. "
400                          "(omx error 0x%08x, internalError %d)",
401                          omxError, internalError);
402
403                    bool sendErrorReponse = true;
404
405                    switch (mState) {
406                        case INITIALIZING:
407                        {
408                            setState(UNINITIALIZED);
409                            break;
410                        }
411
412                        case CONFIGURING:
413                        {
414                            setState(INITIALIZED);
415                            break;
416                        }
417
418                        case STARTING:
419                        {
420                            setState(CONFIGURED);
421                            break;
422                        }
423
424                        case STOPPING:
425                        {
426                            // Ignore the error, assuming we'll still get
427                            // the shutdown complete notification.
428
429                            sendErrorReponse = false;
430                            break;
431                        }
432
433                        case FLUSHING:
434                        {
435                            setState(STARTED);
436                            break;
437                        }
438
439                        case STARTED:
440                        {
441                            sendErrorReponse = false;
442
443                            mFlags |= kFlagStickyError;
444
445                            cancelPendingDequeueOperations();
446                            break;
447                        }
448
449                        default:
450                        {
451                            sendErrorReponse = false;
452
453                            mFlags |= kFlagStickyError;
454                            break;
455                        }
456                    }
457
458                    if (sendErrorReponse) {
459                        sp<AMessage> response = new AMessage;
460                        response->setInt32("err", UNKNOWN_ERROR);
461
462                        response->postReply(mReplyID);
463                    }
464                    break;
465                }
466
467                case ACodec::kWhatComponentAllocated:
468                {
469                    CHECK_EQ(mState, INITIALIZING);
470                    setState(INITIALIZED);
471
472                    AString componentName;
473                    CHECK(msg->findString("componentName", &componentName));
474
475                    if (componentName.startsWith("OMX.google.")) {
476                        mFlags |= kFlagIsSoftwareCodec;
477                    } else {
478                        mFlags &= ~kFlagIsSoftwareCodec;
479                    }
480
481                    (new AMessage)->postReply(mReplyID);
482                    break;
483                }
484
485                case ACodec::kWhatComponentConfigured:
486                {
487                    CHECK_EQ(mState, CONFIGURING);
488                    setState(CONFIGURED);
489
490                    (new AMessage)->postReply(mReplyID);
491                    break;
492                }
493
494                case ACodec::kWhatBuffersAllocated:
495                {
496                    int32_t portIndex;
497                    CHECK(msg->findInt32("portIndex", &portIndex));
498
499                    ALOGV("%s buffers allocated",
500                          portIndex == kPortIndexInput ? "input" : "output");
501
502                    CHECK(portIndex == kPortIndexInput
503                            || portIndex == kPortIndexOutput);
504
505                    mPortBuffers[portIndex].clear();
506
507                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
508                    for (size_t i = 0;; ++i) {
509                        AString name = StringPrintf("buffer-id_%d", i);
510
511                        void *bufferID;
512                        if (!msg->findPointer(name.c_str(), &bufferID)) {
513                            break;
514                        }
515
516                        name = StringPrintf("data_%d", i);
517
518                        BufferInfo info;
519                        info.mBufferID = bufferID;
520                        info.mOwnedByClient = false;
521                        CHECK(msg->findBuffer(name.c_str(), &info.mData));
522
523                        buffers->push_back(info);
524                    }
525
526                    if (portIndex == kPortIndexOutput) {
527                        if (mState == STARTING) {
528                            // We're always allocating output buffers after
529                            // allocating input buffers, so this is a good
530                            // indication that now all buffers are allocated.
531                            setState(STARTED);
532                            (new AMessage)->postReply(mReplyID);
533                        } else {
534                            mFlags |= kFlagOutputBuffersChanged;
535                        }
536                    }
537                    break;
538                }
539
540                case ACodec::kWhatOutputFormatChanged:
541                {
542                    ALOGV("codec output format changed");
543
544                    if ((mFlags & kFlagIsSoftwareCodec)
545                            && mNativeWindow != NULL) {
546                        AString mime;
547                        CHECK(msg->findString("mime", &mime));
548
549                        if (!strncasecmp("video/", mime.c_str(), 6)) {
550                            delete mSoftRenderer;
551                            mSoftRenderer = NULL;
552
553                            int32_t width, height;
554                            CHECK(msg->findInt32("width", &width));
555                            CHECK(msg->findInt32("height", &height));
556
557                            int32_t colorFormat;
558                            CHECK(msg->findInt32(
559                                        "color-format", &colorFormat));
560
561                            sp<MetaData> meta = new MetaData;
562                            meta->setInt32(kKeyWidth, width);
563                            meta->setInt32(kKeyHeight, height);
564                            meta->setInt32(kKeyColorFormat, colorFormat);
565
566                            mSoftRenderer =
567                                new SoftwareRenderer(mNativeWindow, meta);
568                        }
569                    }
570
571                    mOutputFormat = msg;
572                    mFlags |= kFlagOutputFormatChanged;
573                    break;
574                }
575
576                case ACodec::kWhatFillThisBuffer:
577                {
578                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
579
580                    if (mState == FLUSHING) {
581                        returnBuffersToCodecOnPort(kPortIndexInput);
582                        break;
583                    }
584
585                    if (mFlags & kFlagDequeueInputPending) {
586                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
587
588                        ++mDequeueInputTimeoutGeneration;
589                        mFlags &= ~kFlagDequeueInputPending;
590                        mDequeueInputReplyID = 0;
591                    }
592                    break;
593                }
594
595                case ACodec::kWhatDrainThisBuffer:
596                {
597                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
598
599                    if (mState == FLUSHING) {
600                        returnBuffersToCodecOnPort(kPortIndexOutput);
601                        break;
602                    }
603
604                    sp<ABuffer> buffer;
605                    CHECK(msg->findBuffer("buffer", &buffer));
606
607                    int32_t omxFlags;
608                    CHECK(msg->findInt32("flags", &omxFlags));
609
610                    buffer->meta()->setInt32("omxFlags", omxFlags);
611
612                    if (mFlags & kFlagDequeueOutputPending) {
613                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
614
615                        ++mDequeueOutputTimeoutGeneration;
616                        mFlags &= ~kFlagDequeueOutputPending;
617                        mDequeueOutputReplyID = 0;
618                    }
619                    break;
620                }
621
622                case ACodec::kWhatEOS:
623                {
624                    // We already notify the client of this by using the
625                    // corresponding flag in "onOutputBufferReady".
626                    break;
627                }
628
629                case ACodec::kWhatShutdownCompleted:
630                {
631                    CHECK_EQ(mState, STOPPING);
632                    setState(UNINITIALIZED);
633
634                    (new AMessage)->postReply(mReplyID);
635                    break;
636                }
637
638                case ACodec::kWhatFlushCompleted:
639                {
640                    CHECK_EQ(mState, FLUSHING);
641                    setState(STARTED);
642
643                    mCodec->signalResume();
644
645                    (new AMessage)->postReply(mReplyID);
646                    break;
647                }
648
649                default:
650                    TRESPASS();
651            }
652            break;
653        }
654
655        case kWhatInit:
656        {
657            uint32_t replyID;
658            CHECK(msg->senderAwaitsResponse(&replyID));
659
660            if (mState != UNINITIALIZED) {
661                sp<AMessage> response = new AMessage;
662                response->setInt32("err", INVALID_OPERATION);
663
664                response->postReply(replyID);
665                break;
666            }
667
668            mReplyID = replyID;
669            setState(INITIALIZING);
670
671            AString name;
672            CHECK(msg->findString("name", &name));
673
674            int32_t nameIsType;
675            int32_t encoder = false;
676            if (!msg->findInt32("nameIsType", &nameIsType)) {
677                nameIsType = false;
678            } else {
679                CHECK(msg->findInt32("encoder", &encoder));
680            }
681
682            sp<AMessage> format = new AMessage;
683
684            if (nameIsType) {
685                format->setString("mime", name.c_str());
686                format->setInt32("encoder", encoder);
687            } else {
688                format->setString("componentName", name.c_str());
689            }
690
691            mCodec->initiateAllocateComponent(format);
692            break;
693        }
694
695        case kWhatConfigure:
696        {
697            uint32_t replyID;
698            CHECK(msg->senderAwaitsResponse(&replyID));
699
700            if (mState != INITIALIZED) {
701                sp<AMessage> response = new AMessage;
702                response->setInt32("err", INVALID_OPERATION);
703
704                response->postReply(replyID);
705                break;
706            }
707
708            mReplyID = replyID;
709            setState(CONFIGURING);
710
711            sp<RefBase> obj;
712            if (!msg->findObject("native-window", &obj)) {
713                obj.clear();
714            }
715
716            sp<AMessage> format;
717            CHECK(msg->findMessage("format", &format));
718
719            if (obj != NULL) {
720                format->setObject("native-window", obj);
721            }
722
723            uint32_t flags;
724            CHECK(msg->findInt32("flags", (int32_t *)&flags));
725
726            if (flags & CONFIGURE_FLAG_ENCODE) {
727                format->setInt32("encoder", true);
728            }
729
730            mCodec->initiateConfigureComponent(format);
731            break;
732        }
733
734        case kWhatStart:
735        {
736            uint32_t replyID;
737            CHECK(msg->senderAwaitsResponse(&replyID));
738
739            if (mState != CONFIGURED) {
740                sp<AMessage> response = new AMessage;
741                response->setInt32("err", INVALID_OPERATION);
742
743                response->postReply(replyID);
744                break;
745            }
746
747            mReplyID = replyID;
748            setState(STARTING);
749
750            mCodec->initiateStart();
751            break;
752        }
753
754        case kWhatStop:
755        {
756            uint32_t replyID;
757            CHECK(msg->senderAwaitsResponse(&replyID));
758
759            if (mState != INITIALIZED
760                    && mState != CONFIGURED && mState != STARTED) {
761                sp<AMessage> response = new AMessage;
762                response->setInt32("err", INVALID_OPERATION);
763
764                response->postReply(replyID);
765                break;
766            }
767
768            mReplyID = replyID;
769            setState(STOPPING);
770
771            mCodec->initiateShutdown();
772            returnBuffersToCodec();
773            break;
774        }
775
776        case kWhatDequeueInputBuffer:
777        {
778            uint32_t replyID;
779            CHECK(msg->senderAwaitsResponse(&replyID));
780
781            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
782                break;
783            }
784
785            int64_t timeoutUs;
786            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
787
788            if (timeoutUs == 0ll) {
789                sp<AMessage> response = new AMessage;
790                response->setInt32("err", -EAGAIN);
791                response->postReply(replyID);
792                break;
793            }
794
795            mFlags |= kFlagDequeueInputPending;
796            mDequeueInputReplyID = replyID;
797
798            if (timeoutUs > 0ll) {
799                sp<AMessage> timeoutMsg =
800                    new AMessage(kWhatDequeueInputTimedOut, id());
801                timeoutMsg->setInt32(
802                        "generation", ++mDequeueInputTimeoutGeneration);
803                timeoutMsg->post(timeoutUs);
804            }
805            break;
806        }
807
808        case kWhatDequeueInputTimedOut:
809        {
810            int32_t generation;
811            CHECK(msg->findInt32("generation", &generation));
812
813            if (generation != mDequeueInputTimeoutGeneration) {
814                // Obsolete
815                break;
816            }
817
818            CHECK(mFlags & kFlagDequeueInputPending);
819
820            sp<AMessage> response = new AMessage;
821            response->setInt32("err", -EAGAIN);
822            response->postReply(mDequeueInputReplyID);
823
824            mFlags &= ~kFlagDequeueInputPending;
825            mDequeueInputReplyID = 0;
826            break;
827        }
828
829        case kWhatQueueInputBuffer:
830        {
831            uint32_t replyID;
832            CHECK(msg->senderAwaitsResponse(&replyID));
833
834            if (mState != STARTED || (mFlags & kFlagStickyError)) {
835                sp<AMessage> response = new AMessage;
836                response->setInt32("err", INVALID_OPERATION);
837
838                response->postReply(replyID);
839                break;
840            }
841
842            status_t err = onQueueInputBuffer(msg);
843
844            sp<AMessage> response = new AMessage;
845            response->setInt32("err", err);
846            response->postReply(replyID);
847            break;
848        }
849
850        case kWhatDequeueOutputBuffer:
851        {
852            uint32_t replyID;
853            CHECK(msg->senderAwaitsResponse(&replyID));
854
855            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
856                break;
857            }
858
859            int64_t timeoutUs;
860            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
861
862            if (timeoutUs == 0ll) {
863                sp<AMessage> response = new AMessage;
864                response->setInt32("err", -EAGAIN);
865                response->postReply(replyID);
866                break;
867            }
868
869            mFlags |= kFlagDequeueOutputPending;
870            mDequeueOutputReplyID = replyID;
871
872            if (timeoutUs > 0ll) {
873                sp<AMessage> timeoutMsg =
874                    new AMessage(kWhatDequeueOutputTimedOut, id());
875                timeoutMsg->setInt32(
876                        "generation", ++mDequeueOutputTimeoutGeneration);
877                timeoutMsg->post(timeoutUs);
878            }
879            break;
880        }
881
882        case kWhatDequeueOutputTimedOut:
883        {
884            int32_t generation;
885            CHECK(msg->findInt32("generation", &generation));
886
887            if (generation != mDequeueOutputTimeoutGeneration) {
888                // Obsolete
889                break;
890            }
891
892            CHECK(mFlags & kFlagDequeueOutputPending);
893
894            sp<AMessage> response = new AMessage;
895            response->setInt32("err", -EAGAIN);
896            response->postReply(mDequeueOutputReplyID);
897
898            mFlags &= ~kFlagDequeueOutputPending;
899            mDequeueOutputReplyID = 0;
900            break;
901        }
902
903        case kWhatReleaseOutputBuffer:
904        {
905            uint32_t replyID;
906            CHECK(msg->senderAwaitsResponse(&replyID));
907
908            if (mState != STARTED || (mFlags & kFlagStickyError)) {
909                sp<AMessage> response = new AMessage;
910                response->setInt32("err", INVALID_OPERATION);
911
912                response->postReply(replyID);
913                break;
914            }
915
916            status_t err = onReleaseOutputBuffer(msg);
917
918            sp<AMessage> response = new AMessage;
919            response->setInt32("err", err);
920            response->postReply(replyID);
921            break;
922        }
923
924        case kWhatGetBuffers:
925        {
926            uint32_t replyID;
927            CHECK(msg->senderAwaitsResponse(&replyID));
928
929            if (mState != STARTED || (mFlags & kFlagStickyError)) {
930                sp<AMessage> response = new AMessage;
931                response->setInt32("err", INVALID_OPERATION);
932
933                response->postReply(replyID);
934                break;
935            }
936
937            int32_t portIndex;
938            CHECK(msg->findInt32("portIndex", &portIndex));
939
940            Vector<sp<ABuffer> > *dstBuffers;
941            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
942
943            dstBuffers->clear();
944            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
945
946            for (size_t i = 0; i < srcBuffers.size(); ++i) {
947                const BufferInfo &info = srcBuffers.itemAt(i);
948
949                dstBuffers->push_back(info.mData);
950            }
951
952            (new AMessage)->postReply(replyID);
953            break;
954        }
955
956        case kWhatFlush:
957        {
958            uint32_t replyID;
959            CHECK(msg->senderAwaitsResponse(&replyID));
960
961            if (mState != STARTED || (mFlags & kFlagStickyError)) {
962                sp<AMessage> response = new AMessage;
963                response->setInt32("err", INVALID_OPERATION);
964
965                response->postReply(replyID);
966                break;
967            }
968
969            mReplyID = replyID;
970            setState(FLUSHING);
971
972            mCodec->signalFlush();
973            returnBuffersToCodec();
974            break;
975        }
976
977        case kWhatGetOutputFormat:
978        {
979            uint32_t replyID;
980            CHECK(msg->senderAwaitsResponse(&replyID));
981
982            if ((mState != STARTED && mState != FLUSHING)
983                    || (mFlags & kFlagStickyError)) {
984                sp<AMessage> response = new AMessage;
985                response->setInt32("err", INVALID_OPERATION);
986
987                response->postReply(replyID);
988                break;
989            }
990
991            sp<AMessage> response = new AMessage;
992            response->setMessage("format", mOutputFormat);
993            response->postReply(replyID);
994            break;
995        }
996
997        default:
998            TRESPASS();
999    }
1000}
1001
1002void MediaCodec::setState(State newState) {
1003    if (newState == UNINITIALIZED) {
1004        delete mSoftRenderer;
1005        mSoftRenderer = NULL;
1006
1007        mNativeWindow.clear();
1008
1009        mOutputFormat.clear();
1010        mFlags &= ~kFlagOutputFormatChanged;
1011        mFlags &= ~kFlagOutputBuffersChanged;
1012        mFlags &= ~kFlagStickyError;
1013    }
1014
1015    mState = newState;
1016
1017    cancelPendingDequeueOperations();
1018}
1019
1020void MediaCodec::returnBuffersToCodec() {
1021    returnBuffersToCodecOnPort(kPortIndexInput);
1022    returnBuffersToCodecOnPort(kPortIndexOutput);
1023}
1024
1025void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1026    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1027
1028    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1029
1030    for (size_t i = 0; i < buffers->size(); ++i) {
1031        BufferInfo *info = &buffers->editItemAt(i);
1032
1033        if (info->mNotify != NULL) {
1034            sp<AMessage> msg = info->mNotify;
1035            info->mNotify = NULL;
1036            info->mOwnedByClient = false;
1037
1038            if (portIndex == kPortIndexInput) {
1039                msg->setInt32("err", ERROR_END_OF_STREAM);
1040            }
1041            msg->post();
1042        }
1043    }
1044
1045    mAvailPortBuffers[portIndex].clear();
1046}
1047
1048size_t MediaCodec::updateBuffers(
1049        int32_t portIndex, const sp<AMessage> &msg) {
1050    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1051
1052    void *bufferID;
1053    CHECK(msg->findPointer("buffer-id", &bufferID));
1054
1055    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1056
1057    for (size_t i = 0; i < buffers->size(); ++i) {
1058        BufferInfo *info = &buffers->editItemAt(i);
1059
1060        if (info->mBufferID == bufferID) {
1061            CHECK(info->mNotify == NULL);
1062            CHECK(msg->findMessage("reply", &info->mNotify));
1063
1064            mAvailPortBuffers[portIndex].push_back(i);
1065
1066            return i;
1067        }
1068    }
1069
1070    TRESPASS();
1071
1072    return 0;
1073}
1074
1075status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1076    size_t index;
1077    size_t offset;
1078    size_t size;
1079    int64_t timeUs;
1080    uint32_t flags;
1081    CHECK(msg->findSize("index", &index));
1082    CHECK(msg->findSize("offset", &offset));
1083    CHECK(msg->findSize("size", &size));
1084    CHECK(msg->findInt64("timeUs", &timeUs));
1085    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1086
1087    if (index >= mPortBuffers[kPortIndexInput].size()) {
1088        return -ERANGE;
1089    }
1090
1091    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1092
1093    if (info->mNotify == NULL || !info->mOwnedByClient) {
1094        return -EACCES;
1095    }
1096
1097    if (offset + size > info->mData->capacity()) {
1098        return -EINVAL;
1099    }
1100
1101    sp<AMessage> reply = info->mNotify;
1102    info->mNotify = NULL;
1103    info->mOwnedByClient = false;
1104
1105    info->mData->setRange(offset, size);
1106    info->mData->meta()->setInt64("timeUs", timeUs);
1107
1108    if (flags & BUFFER_FLAG_EOS) {
1109        info->mData->meta()->setInt32("eos", true);
1110    }
1111
1112    if (flags & BUFFER_FLAG_CODECCONFIG) {
1113        info->mData->meta()->setInt32("csd", true);
1114    }
1115
1116    reply->setBuffer("buffer", info->mData);
1117    reply->post();
1118
1119    return OK;
1120}
1121
1122status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1123    size_t index;
1124    CHECK(msg->findSize("index", &index));
1125
1126    int32_t render;
1127    if (!msg->findInt32("render", &render)) {
1128        render = 0;
1129    }
1130
1131    if (mState != STARTED) {
1132        return -EINVAL;
1133    }
1134
1135    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1136        return -ERANGE;
1137    }
1138
1139    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1140
1141    if (info->mNotify == NULL || !info->mOwnedByClient) {
1142        return -EACCES;
1143    }
1144
1145    if (render) {
1146        info->mNotify->setInt32("render", true);
1147
1148        if (mSoftRenderer != NULL) {
1149            mSoftRenderer->render(
1150                    info->mData->data(), info->mData->size(), NULL);
1151        }
1152    }
1153
1154    info->mNotify->post();
1155    info->mNotify = NULL;
1156    info->mOwnedByClient = false;
1157
1158    return OK;
1159}
1160
1161ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
1162    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1163
1164    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
1165
1166    if (availBuffers->empty()) {
1167        return -EAGAIN;
1168    }
1169
1170    size_t index = *availBuffers->begin();
1171    availBuffers->erase(availBuffers->begin());
1172
1173    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
1174    CHECK(!info->mOwnedByClient);
1175    info->mOwnedByClient = true;
1176
1177    return index;
1178}
1179
1180}  // namespace android
1181