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