MediaCodec.cpp revision 496238cc7551d414067dcbbb4fe3bd801f205f95
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/ICrypto.h>
27#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/foundation/AString.h>
31#include <media/stagefright/foundation/hexdump.h>
32#include <media/stagefright/ACodec.h>
33#include <media/stagefright/MediaErrors.h>
34#include <media/stagefright/MetaData.h>
35#include <media/stagefright/NativeWindowWrapper.h>
36
37namespace android {
38
39// static
40sp<MediaCodec> MediaCodec::CreateByType(
41        const sp<ALooper> &looper, const char *mime, bool encoder) {
42    sp<MediaCodec> codec = new MediaCodec(looper);
43    if (codec->init(mime, true /* nameIsType */, encoder) != OK) {
44        return NULL;
45    }
46
47    return codec;
48}
49
50// static
51sp<MediaCodec> MediaCodec::CreateByComponentName(
52        const sp<ALooper> &looper, const char *name) {
53    sp<MediaCodec> codec = new MediaCodec(looper);
54    if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) {
55        return NULL;
56    }
57
58    return codec;
59}
60
61MediaCodec::MediaCodec(const sp<ALooper> &looper)
62    : mState(UNINITIALIZED),
63      mLooper(looper),
64      mCodec(new ACodec),
65      mFlags(0),
66      mSoftRenderer(NULL),
67      mDequeueInputTimeoutGeneration(0),
68      mDequeueInputReplyID(0),
69      mDequeueOutputTimeoutGeneration(0),
70      mDequeueOutputReplyID(0) {
71}
72
73MediaCodec::~MediaCodec() {
74    CHECK_EQ(mState, UNINITIALIZED);
75}
76
77// static
78status_t MediaCodec::PostAndAwaitResponse(
79        const sp<AMessage> &msg, sp<AMessage> *response) {
80    status_t err = msg->postAndAwaitResponse(response);
81
82    if (err != OK) {
83        return err;
84    }
85
86    if (!(*response)->findInt32("err", &err)) {
87        err = OK;
88    }
89
90    return err;
91}
92
93status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
94    // Current video decoders do not return from OMX_FillThisBuffer
95    // quickly, violating the OpenMAX specs, until that is remedied
96    // we need to invest in an extra looper to free the main event
97    // queue.
98    bool needDedicatedLooper = false;
99    if (nameIsType && !strncasecmp(name, "video/", 6)) {
100        needDedicatedLooper = true;
101    } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) {
102        needDedicatedLooper = true;
103    }
104
105    if (needDedicatedLooper) {
106        if (mCodecLooper == NULL) {
107            mCodecLooper = new ALooper;
108            mCodecLooper->setName("CodecLooper");
109            mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
110        }
111
112        mCodecLooper->registerHandler(mCodec);
113    } else {
114        mLooper->registerHandler(mCodec);
115    }
116
117    mLooper->registerHandler(this);
118
119    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
120
121    sp<AMessage> msg = new AMessage(kWhatInit, id());
122    msg->setString("name", name);
123    msg->setInt32("nameIsType", nameIsType);
124
125    if (nameIsType) {
126        msg->setInt32("encoder", encoder);
127    }
128
129    sp<AMessage> response;
130    return PostAndAwaitResponse(msg, &response);
131}
132
133status_t MediaCodec::configure(
134        const sp<AMessage> &format,
135        const sp<SurfaceTextureClient> &nativeWindow,
136        const sp<ICrypto> &crypto,
137        uint32_t flags) {
138    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
139
140    msg->setMessage("format", format);
141    msg->setInt32("flags", flags);
142
143    if (nativeWindow != NULL) {
144        msg->setObject(
145                "native-window",
146                new NativeWindowWrapper(nativeWindow));
147    }
148
149    if (crypto != NULL) {
150        msg->setPointer("crypto", crypto.get());
151    }
152
153    sp<AMessage> response;
154    return PostAndAwaitResponse(msg, &response);
155}
156
157status_t MediaCodec::start() {
158    sp<AMessage> msg = new AMessage(kWhatStart, id());
159
160    sp<AMessage> response;
161    return PostAndAwaitResponse(msg, &response);
162}
163
164status_t MediaCodec::stop() {
165    sp<AMessage> msg = new AMessage(kWhatStop, id());
166
167    sp<AMessage> response;
168    return PostAndAwaitResponse(msg, &response);
169}
170
171status_t MediaCodec::release() {
172    sp<AMessage> msg = new AMessage(kWhatRelease, id());
173
174    sp<AMessage> response;
175    return PostAndAwaitResponse(msg, &response);
176}
177
178status_t MediaCodec::queueInputBuffer(
179        size_t index,
180        size_t offset,
181        size_t size,
182        int64_t presentationTimeUs,
183        uint32_t flags,
184        AString *errorDetailMsg) {
185    if (errorDetailMsg != NULL) {
186        errorDetailMsg->clear();
187    }
188
189    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
190    msg->setSize("index", index);
191    msg->setSize("offset", offset);
192    msg->setSize("size", size);
193    msg->setInt64("timeUs", presentationTimeUs);
194    msg->setInt32("flags", flags);
195    msg->setPointer("errorDetailMsg", errorDetailMsg);
196
197    sp<AMessage> response;
198    return PostAndAwaitResponse(msg, &response);
199}
200
201status_t MediaCodec::queueSecureInputBuffer(
202        size_t index,
203        size_t offset,
204        const CryptoPlugin::SubSample *subSamples,
205        size_t numSubSamples,
206        const uint8_t key[16],
207        const uint8_t iv[16],
208        CryptoPlugin::Mode mode,
209        int64_t presentationTimeUs,
210        uint32_t flags,
211        AString *errorDetailMsg) {
212    if (errorDetailMsg != NULL) {
213        errorDetailMsg->clear();
214    }
215
216    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
217    msg->setSize("index", index);
218    msg->setSize("offset", offset);
219    msg->setPointer("subSamples", (void *)subSamples);
220    msg->setSize("numSubSamples", numSubSamples);
221    msg->setPointer("key", (void *)key);
222    msg->setPointer("iv", (void *)iv);
223    msg->setInt32("mode", mode);
224    msg->setInt64("timeUs", presentationTimeUs);
225    msg->setInt32("flags", flags);
226    msg->setPointer("errorDetailMsg", errorDetailMsg);
227
228    sp<AMessage> response;
229    status_t err = PostAndAwaitResponse(msg, &response);
230
231    return err;
232}
233
234status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
235    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
236    msg->setInt64("timeoutUs", timeoutUs);
237
238    sp<AMessage> response;
239    status_t err;
240    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
241        return err;
242    }
243
244    CHECK(response->findSize("index", index));
245
246    return OK;
247}
248
249status_t MediaCodec::dequeueOutputBuffer(
250        size_t *index,
251        size_t *offset,
252        size_t *size,
253        int64_t *presentationTimeUs,
254        uint32_t *flags,
255        int64_t timeoutUs) {
256    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
257    msg->setInt64("timeoutUs", timeoutUs);
258
259    sp<AMessage> response;
260    status_t err;
261    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
262        return err;
263    }
264
265    CHECK(response->findSize("index", index));
266    CHECK(response->findSize("offset", offset));
267    CHECK(response->findSize("size", size));
268    CHECK(response->findInt64("timeUs", presentationTimeUs));
269    CHECK(response->findInt32("flags", (int32_t *)flags));
270
271    return OK;
272}
273
274status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
275    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
276    msg->setSize("index", index);
277    msg->setInt32("render", true);
278
279    sp<AMessage> response;
280    return PostAndAwaitResponse(msg, &response);
281}
282
283status_t MediaCodec::releaseOutputBuffer(size_t index) {
284    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
285    msg->setSize("index", index);
286
287    sp<AMessage> response;
288    return PostAndAwaitResponse(msg, &response);
289}
290
291status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
292    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
293
294    sp<AMessage> response;
295    status_t err;
296    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
297        return err;
298    }
299
300    CHECK(response->findMessage("format", format));
301
302    return OK;
303}
304
305status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
306    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
307    msg->setInt32("portIndex", kPortIndexInput);
308    msg->setPointer("buffers", buffers);
309
310    sp<AMessage> response;
311    return PostAndAwaitResponse(msg, &response);
312}
313
314status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
315    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
316    msg->setInt32("portIndex", kPortIndexOutput);
317    msg->setPointer("buffers", buffers);
318
319    sp<AMessage> response;
320    return PostAndAwaitResponse(msg, &response);
321}
322
323status_t MediaCodec::flush() {
324    sp<AMessage> msg = new AMessage(kWhatFlush, id());
325
326    sp<AMessage> response;
327    return PostAndAwaitResponse(msg, &response);
328}
329
330status_t MediaCodec::requestIDRFrame() {
331    (new AMessage(kWhatRequestIDRFrame, id()))->post();
332
333    return OK;
334}
335
336////////////////////////////////////////////////////////////////////////////////
337
338void MediaCodec::cancelPendingDequeueOperations() {
339    if (mFlags & kFlagDequeueInputPending) {
340        sp<AMessage> response = new AMessage;
341        response->setInt32("err", INVALID_OPERATION);
342        response->postReply(mDequeueInputReplyID);
343
344        ++mDequeueInputTimeoutGeneration;
345        mDequeueInputReplyID = 0;
346        mFlags &= ~kFlagDequeueInputPending;
347    }
348
349    if (mFlags & kFlagDequeueOutputPending) {
350        sp<AMessage> response = new AMessage;
351        response->setInt32("err", INVALID_OPERATION);
352        response->postReply(mDequeueOutputReplyID);
353
354        ++mDequeueOutputTimeoutGeneration;
355        mDequeueOutputReplyID = 0;
356        mFlags &= ~kFlagDequeueOutputPending;
357    }
358}
359
360bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
361    if (mState != STARTED
362            || (mFlags & kFlagStickyError)
363            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
364        sp<AMessage> response = new AMessage;
365        response->setInt32("err", INVALID_OPERATION);
366
367        response->postReply(replyID);
368
369        return true;
370    }
371
372    ssize_t index = dequeuePortBuffer(kPortIndexInput);
373
374    if (index < 0) {
375        CHECK_EQ(index, -EAGAIN);
376        return false;
377    }
378
379    sp<AMessage> response = new AMessage;
380    response->setSize("index", index);
381    response->postReply(replyID);
382
383    return true;
384}
385
386bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
387    sp<AMessage> response = new AMessage;
388
389    if (mState != STARTED
390            || (mFlags & kFlagStickyError)
391            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
392        response->setInt32("err", INVALID_OPERATION);
393    } else if (mFlags & kFlagOutputBuffersChanged) {
394        response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
395        mFlags &= ~kFlagOutputBuffersChanged;
396    } else if (mFlags & kFlagOutputFormatChanged) {
397        response->setInt32("err", INFO_FORMAT_CHANGED);
398        mFlags &= ~kFlagOutputFormatChanged;
399    } else {
400        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
401
402        if (index < 0) {
403            CHECK_EQ(index, -EAGAIN);
404            return false;
405        }
406
407        const sp<ABuffer> &buffer =
408            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
409
410        response->setSize("index", index);
411        response->setSize("offset", buffer->offset());
412        response->setSize("size", buffer->size());
413
414        int64_t timeUs;
415        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
416
417        response->setInt64("timeUs", timeUs);
418
419        int32_t omxFlags;
420        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
421
422        uint32_t flags = 0;
423        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
424            flags |= BUFFER_FLAG_SYNCFRAME;
425        }
426        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
427            flags |= BUFFER_FLAG_CODECCONFIG;
428        }
429        if (omxFlags & OMX_BUFFERFLAG_EOS) {
430            flags |= BUFFER_FLAG_EOS;
431        }
432
433        response->setInt32("flags", flags);
434    }
435
436    response->postReply(replyID);
437
438    return true;
439}
440
441void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
442    switch (msg->what()) {
443        case kWhatCodecNotify:
444        {
445            int32_t what;
446            CHECK(msg->findInt32("what", &what));
447
448            switch (what) {
449                case ACodec::kWhatError:
450                {
451                    int32_t omxError, internalError;
452                    CHECK(msg->findInt32("omx-error", &omxError));
453                    CHECK(msg->findInt32("err", &internalError));
454
455                    ALOGE("Codec reported an error. "
456                          "(omx error 0x%08x, internalError %d)",
457                          omxError, internalError);
458
459                    bool sendErrorReponse = true;
460
461                    switch (mState) {
462                        case INITIALIZING:
463                        {
464                            setState(UNINITIALIZED);
465                            break;
466                        }
467
468                        case CONFIGURING:
469                        {
470                            setState(INITIALIZED);
471                            break;
472                        }
473
474                        case STARTING:
475                        {
476                            setState(CONFIGURED);
477                            break;
478                        }
479
480                        case STOPPING:
481                        case RELEASING:
482                        {
483                            // Ignore the error, assuming we'll still get
484                            // the shutdown complete notification.
485
486                            sendErrorReponse = false;
487                            break;
488                        }
489
490                        case FLUSHING:
491                        {
492                            setState(STARTED);
493                            break;
494                        }
495
496                        case STARTED:
497                        {
498                            sendErrorReponse = false;
499
500                            mFlags |= kFlagStickyError;
501
502                            cancelPendingDequeueOperations();
503                            break;
504                        }
505
506                        default:
507                        {
508                            sendErrorReponse = false;
509
510                            mFlags |= kFlagStickyError;
511                            break;
512                        }
513                    }
514
515                    if (sendErrorReponse) {
516                        sp<AMessage> response = new AMessage;
517                        response->setInt32("err", UNKNOWN_ERROR);
518
519                        response->postReply(mReplyID);
520                    }
521                    break;
522                }
523
524                case ACodec::kWhatComponentAllocated:
525                {
526                    CHECK_EQ(mState, INITIALIZING);
527                    setState(INITIALIZED);
528
529                    AString componentName;
530                    CHECK(msg->findString("componentName", &componentName));
531
532                    if (componentName.startsWith("OMX.google.")) {
533                        mFlags |= kFlagIsSoftwareCodec;
534                    } else {
535                        mFlags &= ~kFlagIsSoftwareCodec;
536                    }
537
538                    if (componentName.endsWith(".secure")) {
539                        mFlags |= kFlagIsSecure;
540                    } else {
541                        mFlags &= ~kFlagIsSecure;
542                    }
543
544                    (new AMessage)->postReply(mReplyID);
545                    break;
546                }
547
548                case ACodec::kWhatComponentConfigured:
549                {
550                    CHECK_EQ(mState, CONFIGURING);
551                    setState(CONFIGURED);
552
553                    (new AMessage)->postReply(mReplyID);
554                    break;
555                }
556
557                case ACodec::kWhatBuffersAllocated:
558                {
559                    int32_t portIndex;
560                    CHECK(msg->findInt32("portIndex", &portIndex));
561
562                    ALOGV("%s buffers allocated",
563                          portIndex == kPortIndexInput ? "input" : "output");
564
565                    CHECK(portIndex == kPortIndexInput
566                            || portIndex == kPortIndexOutput);
567
568                    mPortBuffers[portIndex].clear();
569
570                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
571
572                    sp<RefBase> obj;
573                    CHECK(msg->findObject("portDesc", &obj));
574
575                    sp<ACodec::PortDescription> portDesc =
576                        static_cast<ACodec::PortDescription *>(obj.get());
577
578                    size_t numBuffers = portDesc->countBuffers();
579
580                    for (size_t i = 0; i < numBuffers; ++i) {
581                        BufferInfo info;
582                        info.mBufferID = portDesc->bufferIDAt(i);
583                        info.mOwnedByClient = false;
584                        info.mData = portDesc->bufferAt(i);
585
586                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
587                            info.mEncryptedData =
588                                new ABuffer(info.mData->capacity());
589                        }
590
591                        buffers->push_back(info);
592                    }
593
594                    if (portIndex == kPortIndexOutput) {
595                        if (mState == STARTING) {
596                            // We're always allocating output buffers after
597                            // allocating input buffers, so this is a good
598                            // indication that now all buffers are allocated.
599                            setState(STARTED);
600                            (new AMessage)->postReply(mReplyID);
601                        } else {
602                            mFlags |= kFlagOutputBuffersChanged;
603                        }
604                    }
605                    break;
606                }
607
608                case ACodec::kWhatOutputFormatChanged:
609                {
610                    ALOGV("codec output format changed");
611
612                    if ((mFlags & kFlagIsSoftwareCodec)
613                            && mNativeWindow != NULL) {
614                        AString mime;
615                        CHECK(msg->findString("mime", &mime));
616
617                        if (!strncasecmp("video/", mime.c_str(), 6)) {
618                            delete mSoftRenderer;
619                            mSoftRenderer = NULL;
620
621                            int32_t width, height;
622                            CHECK(msg->findInt32("width", &width));
623                            CHECK(msg->findInt32("height", &height));
624
625                            int32_t colorFormat;
626                            CHECK(msg->findInt32(
627                                        "color-format", &colorFormat));
628
629                            sp<MetaData> meta = new MetaData;
630                            meta->setInt32(kKeyWidth, width);
631                            meta->setInt32(kKeyHeight, height);
632                            meta->setInt32(kKeyColorFormat, colorFormat);
633
634                            mSoftRenderer =
635                                new SoftwareRenderer(mNativeWindow, meta);
636                        }
637                    }
638
639                    mOutputFormat = msg;
640                    mFlags |= kFlagOutputFormatChanged;
641                    break;
642                }
643
644                case ACodec::kWhatFillThisBuffer:
645                {
646                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
647
648                    if (mState == FLUSHING
649                            || mState == STOPPING
650                            || mState == RELEASING) {
651                        returnBuffersToCodecOnPort(kPortIndexInput);
652                        break;
653                    }
654
655                    if (!mCSD.empty()) {
656                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
657                        CHECK_GE(index, 0);
658
659                        // If codec specific data had been specified as
660                        // part of the format in the call to configure and
661                        // if there's more csd left, we submit it here
662                        // clients only get access to input buffers once
663                        // this data has been exhausted.
664
665                        status_t err = queueCSDInputBuffer(index);
666
667                        if (err != OK) {
668                            ALOGE("queueCSDInputBuffer failed w/ error %d",
669                                  err);
670
671                            mFlags |= kFlagStickyError;
672                            cancelPendingDequeueOperations();
673                        }
674                        break;
675                    }
676
677                    if (mFlags & kFlagDequeueInputPending) {
678                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
679
680                        ++mDequeueInputTimeoutGeneration;
681                        mFlags &= ~kFlagDequeueInputPending;
682                        mDequeueInputReplyID = 0;
683                    }
684                    break;
685                }
686
687                case ACodec::kWhatDrainThisBuffer:
688                {
689                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
690
691                    if (mState == FLUSHING
692                            || mState == STOPPING
693                            || mState == RELEASING) {
694                        returnBuffersToCodecOnPort(kPortIndexOutput);
695                        break;
696                    }
697
698                    sp<ABuffer> buffer;
699                    CHECK(msg->findBuffer("buffer", &buffer));
700
701                    int32_t omxFlags;
702                    CHECK(msg->findInt32("flags", &omxFlags));
703
704                    buffer->meta()->setInt32("omxFlags", omxFlags);
705
706                    if (mFlags & kFlagDequeueOutputPending) {
707                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
708
709                        ++mDequeueOutputTimeoutGeneration;
710                        mFlags &= ~kFlagDequeueOutputPending;
711                        mDequeueOutputReplyID = 0;
712                    }
713                    break;
714                }
715
716                case ACodec::kWhatEOS:
717                {
718                    // We already notify the client of this by using the
719                    // corresponding flag in "onOutputBufferReady".
720                    break;
721                }
722
723                case ACodec::kWhatShutdownCompleted:
724                {
725                    if (mState == STOPPING) {
726                        setState(INITIALIZED);
727                    } else {
728                        CHECK_EQ(mState, RELEASING);
729                        setState(UNINITIALIZED);
730                    }
731
732                    (new AMessage)->postReply(mReplyID);
733                    break;
734                }
735
736                case ACodec::kWhatFlushCompleted:
737                {
738                    CHECK_EQ(mState, FLUSHING);
739                    setState(STARTED);
740
741                    mCodec->signalResume();
742
743                    (new AMessage)->postReply(mReplyID);
744                    break;
745                }
746
747                default:
748                    TRESPASS();
749            }
750            break;
751        }
752
753        case kWhatInit:
754        {
755            uint32_t replyID;
756            CHECK(msg->senderAwaitsResponse(&replyID));
757
758            if (mState != UNINITIALIZED) {
759                sp<AMessage> response = new AMessage;
760                response->setInt32("err", INVALID_OPERATION);
761
762                response->postReply(replyID);
763                break;
764            }
765
766            mReplyID = replyID;
767            setState(INITIALIZING);
768
769            AString name;
770            CHECK(msg->findString("name", &name));
771
772            int32_t nameIsType;
773            int32_t encoder = false;
774            CHECK(msg->findInt32("nameIsType", &nameIsType));
775            if (nameIsType) {
776                CHECK(msg->findInt32("encoder", &encoder));
777            }
778
779            sp<AMessage> format = new AMessage;
780
781            if (nameIsType) {
782                format->setString("mime", name.c_str());
783                format->setInt32("encoder", encoder);
784            } else {
785                format->setString("componentName", name.c_str());
786            }
787
788            mCodec->initiateAllocateComponent(format);
789            break;
790        }
791
792        case kWhatConfigure:
793        {
794            uint32_t replyID;
795            CHECK(msg->senderAwaitsResponse(&replyID));
796
797            if (mState != INITIALIZED) {
798                sp<AMessage> response = new AMessage;
799                response->setInt32("err", INVALID_OPERATION);
800
801                response->postReply(replyID);
802                break;
803            }
804
805            sp<RefBase> obj;
806            if (!msg->findObject("native-window", &obj)) {
807                obj.clear();
808            }
809
810            sp<AMessage> format;
811            CHECK(msg->findMessage("format", &format));
812
813            if (obj != NULL) {
814                format->setObject("native-window", obj);
815
816                status_t err = setNativeWindow(
817                    static_cast<NativeWindowWrapper *>(obj.get())
818                        ->getSurfaceTextureClient());
819
820                if (err != OK) {
821                    sp<AMessage> response = new AMessage;
822                    response->setInt32("err", err);
823
824                    response->postReply(replyID);
825                    break;
826                }
827            } else {
828                setNativeWindow(NULL);
829            }
830
831            mReplyID = replyID;
832            setState(CONFIGURING);
833
834            void *crypto;
835            if (!msg->findPointer("crypto", &crypto)) {
836                crypto = NULL;
837            }
838
839            mCrypto = static_cast<ICrypto *>(crypto);
840
841            uint32_t flags;
842            CHECK(msg->findInt32("flags", (int32_t *)&flags));
843
844            if (flags & CONFIGURE_FLAG_ENCODE) {
845                format->setInt32("encoder", true);
846            }
847
848            extractCSD(format);
849
850            mCodec->initiateConfigureComponent(format);
851            break;
852        }
853
854        case kWhatStart:
855        {
856            uint32_t replyID;
857            CHECK(msg->senderAwaitsResponse(&replyID));
858
859            if (mState != CONFIGURED) {
860                sp<AMessage> response = new AMessage;
861                response->setInt32("err", INVALID_OPERATION);
862
863                response->postReply(replyID);
864                break;
865            }
866
867            mReplyID = replyID;
868            setState(STARTING);
869
870            mCodec->initiateStart();
871            break;
872        }
873
874        case kWhatStop:
875        {
876            uint32_t replyID;
877            CHECK(msg->senderAwaitsResponse(&replyID));
878
879            if (mState != INITIALIZED
880                    && mState != CONFIGURED && mState != STARTED) {
881                sp<AMessage> response = new AMessage;
882                response->setInt32("err", INVALID_OPERATION);
883
884                response->postReply(replyID);
885                break;
886            }
887
888            mReplyID = replyID;
889            setState(STOPPING);
890
891            mCodec->initiateShutdown(true /* keepComponentAllocated */);
892            returnBuffersToCodec();
893            break;
894        }
895
896        case kWhatRelease:
897        {
898            uint32_t replyID;
899            CHECK(msg->senderAwaitsResponse(&replyID));
900
901            if (mState != INITIALIZED
902                    && mState != CONFIGURED && mState != STARTED) {
903                sp<AMessage> response = new AMessage;
904                response->setInt32("err", INVALID_OPERATION);
905
906                response->postReply(replyID);
907                break;
908            }
909
910            mReplyID = replyID;
911            setState(RELEASING);
912
913            mCodec->initiateShutdown();
914            returnBuffersToCodec();
915            break;
916        }
917
918        case kWhatDequeueInputBuffer:
919        {
920            uint32_t replyID;
921            CHECK(msg->senderAwaitsResponse(&replyID));
922
923            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
924                break;
925            }
926
927            int64_t timeoutUs;
928            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
929
930            if (timeoutUs == 0ll) {
931                sp<AMessage> response = new AMessage;
932                response->setInt32("err", -EAGAIN);
933                response->postReply(replyID);
934                break;
935            }
936
937            mFlags |= kFlagDequeueInputPending;
938            mDequeueInputReplyID = replyID;
939
940            if (timeoutUs > 0ll) {
941                sp<AMessage> timeoutMsg =
942                    new AMessage(kWhatDequeueInputTimedOut, id());
943                timeoutMsg->setInt32(
944                        "generation", ++mDequeueInputTimeoutGeneration);
945                timeoutMsg->post(timeoutUs);
946            }
947            break;
948        }
949
950        case kWhatDequeueInputTimedOut:
951        {
952            int32_t generation;
953            CHECK(msg->findInt32("generation", &generation));
954
955            if (generation != mDequeueInputTimeoutGeneration) {
956                // Obsolete
957                break;
958            }
959
960            CHECK(mFlags & kFlagDequeueInputPending);
961
962            sp<AMessage> response = new AMessage;
963            response->setInt32("err", -EAGAIN);
964            response->postReply(mDequeueInputReplyID);
965
966            mFlags &= ~kFlagDequeueInputPending;
967            mDequeueInputReplyID = 0;
968            break;
969        }
970
971        case kWhatQueueInputBuffer:
972        {
973            uint32_t replyID;
974            CHECK(msg->senderAwaitsResponse(&replyID));
975
976            if (mState != STARTED || (mFlags & kFlagStickyError)) {
977                sp<AMessage> response = new AMessage;
978                response->setInt32("err", INVALID_OPERATION);
979
980                response->postReply(replyID);
981                break;
982            }
983
984            status_t err = onQueueInputBuffer(msg);
985
986            sp<AMessage> response = new AMessage;
987            response->setInt32("err", err);
988            response->postReply(replyID);
989            break;
990        }
991
992        case kWhatDequeueOutputBuffer:
993        {
994            uint32_t replyID;
995            CHECK(msg->senderAwaitsResponse(&replyID));
996
997            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
998                break;
999            }
1000
1001            int64_t timeoutUs;
1002            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1003
1004            if (timeoutUs == 0ll) {
1005                sp<AMessage> response = new AMessage;
1006                response->setInt32("err", -EAGAIN);
1007                response->postReply(replyID);
1008                break;
1009            }
1010
1011            mFlags |= kFlagDequeueOutputPending;
1012            mDequeueOutputReplyID = replyID;
1013
1014            if (timeoutUs > 0ll) {
1015                sp<AMessage> timeoutMsg =
1016                    new AMessage(kWhatDequeueOutputTimedOut, id());
1017                timeoutMsg->setInt32(
1018                        "generation", ++mDequeueOutputTimeoutGeneration);
1019                timeoutMsg->post(timeoutUs);
1020            }
1021            break;
1022        }
1023
1024        case kWhatDequeueOutputTimedOut:
1025        {
1026            int32_t generation;
1027            CHECK(msg->findInt32("generation", &generation));
1028
1029            if (generation != mDequeueOutputTimeoutGeneration) {
1030                // Obsolete
1031                break;
1032            }
1033
1034            CHECK(mFlags & kFlagDequeueOutputPending);
1035
1036            sp<AMessage> response = new AMessage;
1037            response->setInt32("err", -EAGAIN);
1038            response->postReply(mDequeueOutputReplyID);
1039
1040            mFlags &= ~kFlagDequeueOutputPending;
1041            mDequeueOutputReplyID = 0;
1042            break;
1043        }
1044
1045        case kWhatReleaseOutputBuffer:
1046        {
1047            uint32_t replyID;
1048            CHECK(msg->senderAwaitsResponse(&replyID));
1049
1050            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1051                sp<AMessage> response = new AMessage;
1052                response->setInt32("err", INVALID_OPERATION);
1053
1054                response->postReply(replyID);
1055                break;
1056            }
1057
1058            status_t err = onReleaseOutputBuffer(msg);
1059
1060            sp<AMessage> response = new AMessage;
1061            response->setInt32("err", err);
1062            response->postReply(replyID);
1063            break;
1064        }
1065
1066        case kWhatGetBuffers:
1067        {
1068            uint32_t replyID;
1069            CHECK(msg->senderAwaitsResponse(&replyID));
1070
1071            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1072                sp<AMessage> response = new AMessage;
1073                response->setInt32("err", INVALID_OPERATION);
1074
1075                response->postReply(replyID);
1076                break;
1077            }
1078
1079            int32_t portIndex;
1080            CHECK(msg->findInt32("portIndex", &portIndex));
1081
1082            Vector<sp<ABuffer> > *dstBuffers;
1083            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1084
1085            dstBuffers->clear();
1086            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1087
1088            for (size_t i = 0; i < srcBuffers.size(); ++i) {
1089                const BufferInfo &info = srcBuffers.itemAt(i);
1090
1091                dstBuffers->push_back(
1092                        (portIndex == kPortIndexInput && mCrypto != NULL)
1093                                ? info.mEncryptedData : info.mData);
1094            }
1095
1096            (new AMessage)->postReply(replyID);
1097            break;
1098        }
1099
1100        case kWhatFlush:
1101        {
1102            uint32_t replyID;
1103            CHECK(msg->senderAwaitsResponse(&replyID));
1104
1105            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1106                sp<AMessage> response = new AMessage;
1107                response->setInt32("err", INVALID_OPERATION);
1108
1109                response->postReply(replyID);
1110                break;
1111            }
1112
1113            mReplyID = replyID;
1114            setState(FLUSHING);
1115
1116            mCodec->signalFlush();
1117            returnBuffersToCodec();
1118            break;
1119        }
1120
1121        case kWhatGetOutputFormat:
1122        {
1123            uint32_t replyID;
1124            CHECK(msg->senderAwaitsResponse(&replyID));
1125
1126            if ((mState != STARTED && mState != FLUSHING)
1127                    || (mFlags & kFlagStickyError)
1128                    || mOutputFormat == NULL) {
1129                sp<AMessage> response = new AMessage;
1130                response->setInt32("err", INVALID_OPERATION);
1131
1132                response->postReply(replyID);
1133                break;
1134            }
1135
1136            sp<AMessage> response = new AMessage;
1137            response->setMessage("format", mOutputFormat);
1138            response->postReply(replyID);
1139            break;
1140        }
1141
1142        case kWhatRequestIDRFrame:
1143        {
1144            mCodec->signalRequestIDRFrame();
1145            break;
1146        }
1147
1148        default:
1149            TRESPASS();
1150    }
1151}
1152
1153void MediaCodec::extractCSD(const sp<AMessage> &format) {
1154    mCSD.clear();
1155
1156    size_t i = 0;
1157    for (;;) {
1158        sp<ABuffer> csd;
1159        if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
1160            break;
1161        }
1162
1163        mCSD.push_back(csd);
1164        ++i;
1165    }
1166
1167    ALOGV("Found %u pieces of codec specific data.", mCSD.size());
1168}
1169
1170status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1171    CHECK(!mCSD.empty());
1172
1173    BufferInfo *info =
1174        &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex);
1175
1176    sp<ABuffer> csd = *mCSD.begin();
1177    mCSD.erase(mCSD.begin());
1178
1179    const sp<ABuffer> &codecInputData =
1180        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1181
1182    if (csd->size() > codecInputData->capacity()) {
1183        return -EINVAL;
1184    }
1185
1186    memcpy(codecInputData->data(), csd->data(), csd->size());
1187
1188    AString errorDetailMsg;
1189
1190    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1191    msg->setSize("index", bufferIndex);
1192    msg->setSize("offset", 0);
1193    msg->setSize("size", csd->size());
1194    msg->setInt64("timeUs", 0ll);
1195    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1196    msg->setPointer("errorDetailMsg", &errorDetailMsg);
1197
1198    return onQueueInputBuffer(msg);
1199}
1200
1201void MediaCodec::setState(State newState) {
1202    if (newState == INITIALIZED || newState == UNINITIALIZED) {
1203        delete mSoftRenderer;
1204        mSoftRenderer = NULL;
1205
1206        mCrypto.clear();
1207        setNativeWindow(NULL);
1208
1209        mOutputFormat.clear();
1210        mFlags &= ~kFlagOutputFormatChanged;
1211        mFlags &= ~kFlagOutputBuffersChanged;
1212        mFlags &= ~kFlagStickyError;
1213    }
1214
1215    mState = newState;
1216
1217    cancelPendingDequeueOperations();
1218}
1219
1220void MediaCodec::returnBuffersToCodec() {
1221    returnBuffersToCodecOnPort(kPortIndexInput);
1222    returnBuffersToCodecOnPort(kPortIndexOutput);
1223}
1224
1225void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1226    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1227
1228    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1229
1230    for (size_t i = 0; i < buffers->size(); ++i) {
1231        BufferInfo *info = &buffers->editItemAt(i);
1232
1233        if (info->mNotify != NULL) {
1234            sp<AMessage> msg = info->mNotify;
1235            info->mNotify = NULL;
1236            info->mOwnedByClient = false;
1237
1238            if (portIndex == kPortIndexInput) {
1239                msg->setInt32("err", ERROR_END_OF_STREAM);
1240            }
1241            msg->post();
1242        }
1243    }
1244
1245    mAvailPortBuffers[portIndex].clear();
1246}
1247
1248size_t MediaCodec::updateBuffers(
1249        int32_t portIndex, const sp<AMessage> &msg) {
1250    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1251
1252    void *bufferID;
1253    CHECK(msg->findPointer("buffer-id", &bufferID));
1254
1255    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1256
1257    for (size_t i = 0; i < buffers->size(); ++i) {
1258        BufferInfo *info = &buffers->editItemAt(i);
1259
1260        if (info->mBufferID == bufferID) {
1261            CHECK(info->mNotify == NULL);
1262            CHECK(msg->findMessage("reply", &info->mNotify));
1263
1264            mAvailPortBuffers[portIndex].push_back(i);
1265
1266            return i;
1267        }
1268    }
1269
1270    TRESPASS();
1271
1272    return 0;
1273}
1274
1275status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1276    size_t index;
1277    size_t offset;
1278    size_t size;
1279    int64_t timeUs;
1280    uint32_t flags;
1281    CHECK(msg->findSize("index", &index));
1282    CHECK(msg->findSize("offset", &offset));
1283    CHECK(msg->findInt64("timeUs", &timeUs));
1284    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1285
1286    const CryptoPlugin::SubSample *subSamples;
1287    size_t numSubSamples;
1288    const uint8_t *key;
1289    const uint8_t *iv;
1290    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1291
1292    // We allow the simpler queueInputBuffer API to be used even in
1293    // secure mode, by fabricating a single unencrypted subSample.
1294    CryptoPlugin::SubSample ss;
1295
1296    if (msg->findSize("size", &size)) {
1297        if (mCrypto != NULL) {
1298            ss.mNumBytesOfClearData = size;
1299            ss.mNumBytesOfEncryptedData = 0;
1300
1301            subSamples = &ss;
1302            numSubSamples = 1;
1303            key = NULL;
1304            iv = NULL;
1305        }
1306    } else {
1307        if (mCrypto == NULL) {
1308            return -EINVAL;
1309        }
1310
1311        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1312        CHECK(msg->findSize("numSubSamples", &numSubSamples));
1313        CHECK(msg->findPointer("key", (void **)&key));
1314        CHECK(msg->findPointer("iv", (void **)&iv));
1315
1316        int32_t tmp;
1317        CHECK(msg->findInt32("mode", &tmp));
1318
1319        mode = (CryptoPlugin::Mode)tmp;
1320
1321        size = 0;
1322        for (size_t i = 0; i < numSubSamples; ++i) {
1323            size += subSamples[i].mNumBytesOfClearData;
1324            size += subSamples[i].mNumBytesOfEncryptedData;
1325        }
1326    }
1327
1328    if (index >= mPortBuffers[kPortIndexInput].size()) {
1329        return -ERANGE;
1330    }
1331
1332    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1333
1334    if (info->mNotify == NULL || !info->mOwnedByClient) {
1335        return -EACCES;
1336    }
1337
1338    if (offset + size > info->mData->capacity()) {
1339        return -EINVAL;
1340    }
1341
1342    sp<AMessage> reply = info->mNotify;
1343    info->mData->setRange(offset, size);
1344    info->mData->meta()->setInt64("timeUs", timeUs);
1345
1346    if (flags & BUFFER_FLAG_EOS) {
1347        info->mData->meta()->setInt32("eos", true);
1348    }
1349
1350    if (flags & BUFFER_FLAG_CODECCONFIG) {
1351        info->mData->meta()->setInt32("csd", true);
1352    }
1353
1354    if (mCrypto != NULL) {
1355        if (size > info->mEncryptedData->capacity()) {
1356            return -ERANGE;
1357        }
1358
1359        AString *errorDetailMsg;
1360        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1361
1362        ssize_t result = mCrypto->decrypt(
1363                (mFlags & kFlagIsSecure) != 0,
1364                key,
1365                iv,
1366                mode,
1367                info->mEncryptedData->base() + offset,
1368                subSamples,
1369                numSubSamples,
1370                info->mData->base(),
1371                errorDetailMsg);
1372
1373        if (result < 0) {
1374            return result;
1375        }
1376
1377        info->mData->setRange(0, result);
1378    }
1379
1380    reply->setBuffer("buffer", info->mData);
1381    reply->post();
1382
1383    info->mNotify = NULL;
1384    info->mOwnedByClient = false;
1385
1386    return OK;
1387}
1388
1389status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1390    size_t index;
1391    CHECK(msg->findSize("index", &index));
1392
1393    int32_t render;
1394    if (!msg->findInt32("render", &render)) {
1395        render = 0;
1396    }
1397
1398    if (mState != STARTED) {
1399        return -EINVAL;
1400    }
1401
1402    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1403        return -ERANGE;
1404    }
1405
1406    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1407
1408    if (info->mNotify == NULL || !info->mOwnedByClient) {
1409        return -EACCES;
1410    }
1411
1412    if (render) {
1413        info->mNotify->setInt32("render", true);
1414
1415        if (mSoftRenderer != NULL) {
1416            mSoftRenderer->render(
1417                    info->mData->data(), info->mData->size(), NULL);
1418        }
1419    }
1420
1421    info->mNotify->post();
1422    info->mNotify = NULL;
1423    info->mOwnedByClient = false;
1424
1425    return OK;
1426}
1427
1428ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
1429    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1430
1431    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
1432
1433    if (availBuffers->empty()) {
1434        return -EAGAIN;
1435    }
1436
1437    size_t index = *availBuffers->begin();
1438    availBuffers->erase(availBuffers->begin());
1439
1440    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
1441    CHECK(!info->mOwnedByClient);
1442    info->mOwnedByClient = true;
1443
1444    return index;
1445}
1446
1447status_t MediaCodec::setNativeWindow(
1448        const sp<SurfaceTextureClient> &surfaceTextureClient) {
1449    status_t err;
1450
1451    if (mNativeWindow != NULL) {
1452        err = native_window_api_disconnect(
1453                mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
1454
1455        if (err != OK) {
1456            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
1457                    strerror(-err), err);
1458        }
1459
1460        mNativeWindow.clear();
1461    }
1462
1463    if (surfaceTextureClient != NULL) {
1464        err = native_window_api_connect(
1465                surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
1466
1467        if (err != OK) {
1468            ALOGE("native_window_api_connect returned an error: %s (%d)",
1469                    strerror(-err), err);
1470
1471            return err;
1472        }
1473
1474        mNativeWindow = surfaceTextureClient;
1475    }
1476
1477    return OK;
1478}
1479
1480}  // namespace android
1481