MediaCodec.cpp revision 7541ff5d83a3e77cb533841a0326a241550b95d9
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
330////////////////////////////////////////////////////////////////////////////////
331
332void MediaCodec::cancelPendingDequeueOperations() {
333    if (mFlags & kFlagDequeueInputPending) {
334        sp<AMessage> response = new AMessage;
335        response->setInt32("err", INVALID_OPERATION);
336        response->postReply(mDequeueInputReplyID);
337
338        ++mDequeueInputTimeoutGeneration;
339        mDequeueInputReplyID = 0;
340        mFlags &= ~kFlagDequeueInputPending;
341    }
342
343    if (mFlags & kFlagDequeueOutputPending) {
344        sp<AMessage> response = new AMessage;
345        response->setInt32("err", INVALID_OPERATION);
346        response->postReply(mDequeueOutputReplyID);
347
348        ++mDequeueOutputTimeoutGeneration;
349        mDequeueOutputReplyID = 0;
350        mFlags &= ~kFlagDequeueOutputPending;
351    }
352}
353
354bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
355    if (mState != STARTED
356            || (mFlags & kFlagStickyError)
357            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
358        sp<AMessage> response = new AMessage;
359        response->setInt32("err", INVALID_OPERATION);
360
361        response->postReply(replyID);
362
363        return true;
364    }
365
366    ssize_t index = dequeuePortBuffer(kPortIndexInput);
367
368    if (index < 0) {
369        CHECK_EQ(index, -EAGAIN);
370        return false;
371    }
372
373    sp<AMessage> response = new AMessage;
374    response->setSize("index", index);
375    response->postReply(replyID);
376
377    return true;
378}
379
380bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
381    sp<AMessage> response = new AMessage;
382
383    if (mState != STARTED
384            || (mFlags & kFlagStickyError)
385            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
386        response->setInt32("err", INVALID_OPERATION);
387    } else if (mFlags & kFlagOutputBuffersChanged) {
388        response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
389        mFlags &= ~kFlagOutputBuffersChanged;
390    } else if (mFlags & kFlagOutputFormatChanged) {
391        response->setInt32("err", INFO_FORMAT_CHANGED);
392        mFlags &= ~kFlagOutputFormatChanged;
393    } else {
394        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
395
396        if (index < 0) {
397            CHECK_EQ(index, -EAGAIN);
398            return false;
399        }
400
401        const sp<ABuffer> &buffer =
402            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
403
404        response->setSize("index", index);
405        response->setSize("offset", buffer->offset());
406        response->setSize("size", buffer->size());
407
408        int64_t timeUs;
409        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
410
411        response->setInt64("timeUs", timeUs);
412
413        int32_t omxFlags;
414        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
415
416        uint32_t flags = 0;
417        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
418            flags |= BUFFER_FLAG_SYNCFRAME;
419        }
420        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
421            flags |= BUFFER_FLAG_CODECCONFIG;
422        }
423        if (omxFlags & OMX_BUFFERFLAG_EOS) {
424            flags |= BUFFER_FLAG_EOS;
425        }
426
427        response->setInt32("flags", flags);
428    }
429
430    response->postReply(replyID);
431
432    return true;
433}
434
435void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
436    switch (msg->what()) {
437        case kWhatCodecNotify:
438        {
439            int32_t what;
440            CHECK(msg->findInt32("what", &what));
441
442            switch (what) {
443                case ACodec::kWhatError:
444                {
445                    int32_t omxError, internalError;
446                    CHECK(msg->findInt32("omx-error", &omxError));
447                    CHECK(msg->findInt32("err", &internalError));
448
449                    ALOGE("Codec reported an error. "
450                          "(omx error 0x%08x, internalError %d)",
451                          omxError, internalError);
452
453                    bool sendErrorReponse = true;
454
455                    switch (mState) {
456                        case INITIALIZING:
457                        {
458                            setState(UNINITIALIZED);
459                            break;
460                        }
461
462                        case CONFIGURING:
463                        {
464                            setState(INITIALIZED);
465                            break;
466                        }
467
468                        case STARTING:
469                        {
470                            setState(CONFIGURED);
471                            break;
472                        }
473
474                        case STOPPING:
475                        case RELEASING:
476                        {
477                            // Ignore the error, assuming we'll still get
478                            // the shutdown complete notification.
479
480                            sendErrorReponse = false;
481                            break;
482                        }
483
484                        case FLUSHING:
485                        {
486                            setState(STARTED);
487                            break;
488                        }
489
490                        case STARTED:
491                        {
492                            sendErrorReponse = false;
493
494                            mFlags |= kFlagStickyError;
495
496                            cancelPendingDequeueOperations();
497                            break;
498                        }
499
500                        default:
501                        {
502                            sendErrorReponse = false;
503
504                            mFlags |= kFlagStickyError;
505                            break;
506                        }
507                    }
508
509                    if (sendErrorReponse) {
510                        sp<AMessage> response = new AMessage;
511                        response->setInt32("err", UNKNOWN_ERROR);
512
513                        response->postReply(mReplyID);
514                    }
515                    break;
516                }
517
518                case ACodec::kWhatComponentAllocated:
519                {
520                    CHECK_EQ(mState, INITIALIZING);
521                    setState(INITIALIZED);
522
523                    AString componentName;
524                    CHECK(msg->findString("componentName", &componentName));
525
526                    if (componentName.startsWith("OMX.google.")) {
527                        mFlags |= kFlagIsSoftwareCodec;
528                    } else {
529                        mFlags &= ~kFlagIsSoftwareCodec;
530                    }
531
532                    if (componentName.endsWith(".secure")) {
533                        mFlags |= kFlagIsSecure;
534                    } else {
535                        mFlags &= ~kFlagIsSecure;
536                    }
537
538                    (new AMessage)->postReply(mReplyID);
539                    break;
540                }
541
542                case ACodec::kWhatComponentConfigured:
543                {
544                    CHECK_EQ(mState, CONFIGURING);
545                    setState(CONFIGURED);
546
547                    (new AMessage)->postReply(mReplyID);
548                    break;
549                }
550
551                case ACodec::kWhatBuffersAllocated:
552                {
553                    int32_t portIndex;
554                    CHECK(msg->findInt32("portIndex", &portIndex));
555
556                    ALOGV("%s buffers allocated",
557                          portIndex == kPortIndexInput ? "input" : "output");
558
559                    CHECK(portIndex == kPortIndexInput
560                            || portIndex == kPortIndexOutput);
561
562                    mPortBuffers[portIndex].clear();
563
564                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
565                    for (size_t i = 0;; ++i) {
566                        AString name = StringPrintf("buffer-id_%d", i);
567
568                        void *bufferID;
569                        if (!msg->findPointer(name.c_str(), &bufferID)) {
570                            break;
571                        }
572
573                        name = StringPrintf("data_%d", i);
574
575                        BufferInfo info;
576                        info.mBufferID = bufferID;
577                        info.mOwnedByClient = false;
578                        CHECK(msg->findBuffer(name.c_str(), &info.mData));
579
580                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
581                            info.mEncryptedData =
582                                new ABuffer(info.mData->capacity());
583                        }
584
585                        buffers->push_back(info);
586                    }
587
588                    if (portIndex == kPortIndexOutput) {
589                        if (mState == STARTING) {
590                            // We're always allocating output buffers after
591                            // allocating input buffers, so this is a good
592                            // indication that now all buffers are allocated.
593                            setState(STARTED);
594                            (new AMessage)->postReply(mReplyID);
595                        } else {
596                            mFlags |= kFlagOutputBuffersChanged;
597                        }
598                    }
599                    break;
600                }
601
602                case ACodec::kWhatOutputFormatChanged:
603                {
604                    ALOGV("codec output format changed");
605
606                    if ((mFlags & kFlagIsSoftwareCodec)
607                            && mNativeWindow != NULL) {
608                        AString mime;
609                        CHECK(msg->findString("mime", &mime));
610
611                        if (!strncasecmp("video/", mime.c_str(), 6)) {
612                            delete mSoftRenderer;
613                            mSoftRenderer = NULL;
614
615                            int32_t width, height;
616                            CHECK(msg->findInt32("width", &width));
617                            CHECK(msg->findInt32("height", &height));
618
619                            int32_t colorFormat;
620                            CHECK(msg->findInt32(
621                                        "color-format", &colorFormat));
622
623                            sp<MetaData> meta = new MetaData;
624                            meta->setInt32(kKeyWidth, width);
625                            meta->setInt32(kKeyHeight, height);
626                            meta->setInt32(kKeyColorFormat, colorFormat);
627
628                            mSoftRenderer =
629                                new SoftwareRenderer(mNativeWindow, meta);
630                        }
631                    }
632
633                    mOutputFormat = msg;
634                    mFlags |= kFlagOutputFormatChanged;
635                    break;
636                }
637
638                case ACodec::kWhatFillThisBuffer:
639                {
640                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
641
642                    if (mState == FLUSHING
643                            || mState == STOPPING
644                            || mState == RELEASING) {
645                        returnBuffersToCodecOnPort(kPortIndexInput);
646                        break;
647                    }
648
649                    if (!mCSD.empty()) {
650                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
651                        CHECK_GE(index, 0);
652
653                        // If codec specific data had been specified as
654                        // part of the format in the call to configure and
655                        // if there's more csd left, we submit it here
656                        // clients only get access to input buffers once
657                        // this data has been exhausted.
658
659                        status_t err = queueCSDInputBuffer(index);
660
661                        if (err != OK) {
662                            ALOGE("queueCSDInputBuffer failed w/ error %d",
663                                  err);
664
665                            mFlags |= kFlagStickyError;
666                            cancelPendingDequeueOperations();
667                        }
668                        break;
669                    }
670
671                    if (mFlags & kFlagDequeueInputPending) {
672                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
673
674                        ++mDequeueInputTimeoutGeneration;
675                        mFlags &= ~kFlagDequeueInputPending;
676                        mDequeueInputReplyID = 0;
677                    }
678                    break;
679                }
680
681                case ACodec::kWhatDrainThisBuffer:
682                {
683                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
684
685                    if (mState == FLUSHING
686                            || mState == STOPPING
687                            || mState == RELEASING) {
688                        returnBuffersToCodecOnPort(kPortIndexOutput);
689                        break;
690                    }
691
692                    sp<ABuffer> buffer;
693                    CHECK(msg->findBuffer("buffer", &buffer));
694
695                    int32_t omxFlags;
696                    CHECK(msg->findInt32("flags", &omxFlags));
697
698                    buffer->meta()->setInt32("omxFlags", omxFlags);
699
700                    if (mFlags & kFlagDequeueOutputPending) {
701                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
702
703                        ++mDequeueOutputTimeoutGeneration;
704                        mFlags &= ~kFlagDequeueOutputPending;
705                        mDequeueOutputReplyID = 0;
706                    }
707                    break;
708                }
709
710                case ACodec::kWhatEOS:
711                {
712                    // We already notify the client of this by using the
713                    // corresponding flag in "onOutputBufferReady".
714                    break;
715                }
716
717                case ACodec::kWhatShutdownCompleted:
718                {
719                    if (mState == STOPPING) {
720                        setState(INITIALIZED);
721                    } else {
722                        CHECK_EQ(mState, RELEASING);
723                        setState(UNINITIALIZED);
724                    }
725
726                    (new AMessage)->postReply(mReplyID);
727                    break;
728                }
729
730                case ACodec::kWhatFlushCompleted:
731                {
732                    CHECK_EQ(mState, FLUSHING);
733                    setState(STARTED);
734
735                    mCodec->signalResume();
736
737                    (new AMessage)->postReply(mReplyID);
738                    break;
739                }
740
741                default:
742                    TRESPASS();
743            }
744            break;
745        }
746
747        case kWhatInit:
748        {
749            uint32_t replyID;
750            CHECK(msg->senderAwaitsResponse(&replyID));
751
752            if (mState != UNINITIALIZED) {
753                sp<AMessage> response = new AMessage;
754                response->setInt32("err", INVALID_OPERATION);
755
756                response->postReply(replyID);
757                break;
758            }
759
760            mReplyID = replyID;
761            setState(INITIALIZING);
762
763            AString name;
764            CHECK(msg->findString("name", &name));
765
766            int32_t nameIsType;
767            int32_t encoder = false;
768            CHECK(msg->findInt32("nameIsType", &nameIsType));
769            if (nameIsType) {
770                CHECK(msg->findInt32("encoder", &encoder));
771            }
772
773            sp<AMessage> format = new AMessage;
774
775            if (nameIsType) {
776                format->setString("mime", name.c_str());
777                format->setInt32("encoder", encoder);
778            } else {
779                format->setString("componentName", name.c_str());
780            }
781
782            mCodec->initiateAllocateComponent(format);
783            break;
784        }
785
786        case kWhatConfigure:
787        {
788            uint32_t replyID;
789            CHECK(msg->senderAwaitsResponse(&replyID));
790
791            if (mState != INITIALIZED) {
792                sp<AMessage> response = new AMessage;
793                response->setInt32("err", INVALID_OPERATION);
794
795                response->postReply(replyID);
796                break;
797            }
798
799            sp<RefBase> obj;
800            if (!msg->findObject("native-window", &obj)) {
801                obj.clear();
802            }
803
804            sp<AMessage> format;
805            CHECK(msg->findMessage("format", &format));
806
807            if (obj != NULL) {
808                format->setObject("native-window", obj);
809
810                status_t err = setNativeWindow(
811                    static_cast<NativeWindowWrapper *>(obj.get())
812                        ->getSurfaceTextureClient());
813
814                if (err != OK) {
815                    sp<AMessage> response = new AMessage;
816                    response->setInt32("err", err);
817
818                    response->postReply(replyID);
819                    break;
820                }
821            } else {
822                setNativeWindow(NULL);
823            }
824
825            mReplyID = replyID;
826            setState(CONFIGURING);
827
828            void *crypto;
829            if (!msg->findPointer("crypto", &crypto)) {
830                crypto = NULL;
831            }
832
833            mCrypto = static_cast<ICrypto *>(crypto);
834
835            uint32_t flags;
836            CHECK(msg->findInt32("flags", (int32_t *)&flags));
837
838            if (flags & CONFIGURE_FLAG_ENCODE) {
839                format->setInt32("encoder", true);
840            }
841
842            extractCSD(format);
843
844            mCodec->initiateConfigureComponent(format);
845            break;
846        }
847
848        case kWhatStart:
849        {
850            uint32_t replyID;
851            CHECK(msg->senderAwaitsResponse(&replyID));
852
853            if (mState != CONFIGURED) {
854                sp<AMessage> response = new AMessage;
855                response->setInt32("err", INVALID_OPERATION);
856
857                response->postReply(replyID);
858                break;
859            }
860
861            mReplyID = replyID;
862            setState(STARTING);
863
864            mCodec->initiateStart();
865            break;
866        }
867
868        case kWhatStop:
869        {
870            uint32_t replyID;
871            CHECK(msg->senderAwaitsResponse(&replyID));
872
873            if (mState != INITIALIZED
874                    && mState != CONFIGURED && mState != STARTED) {
875                sp<AMessage> response = new AMessage;
876                response->setInt32("err", INVALID_OPERATION);
877
878                response->postReply(replyID);
879                break;
880            }
881
882            mReplyID = replyID;
883            setState(STOPPING);
884
885            mCodec->initiateShutdown(true /* keepComponentAllocated */);
886            returnBuffersToCodec();
887            break;
888        }
889
890        case kWhatRelease:
891        {
892            uint32_t replyID;
893            CHECK(msg->senderAwaitsResponse(&replyID));
894
895            if (mState != INITIALIZED
896                    && mState != CONFIGURED && mState != STARTED) {
897                sp<AMessage> response = new AMessage;
898                response->setInt32("err", INVALID_OPERATION);
899
900                response->postReply(replyID);
901                break;
902            }
903
904            mReplyID = replyID;
905            setState(RELEASING);
906
907            mCodec->initiateShutdown();
908            returnBuffersToCodec();
909            break;
910        }
911
912        case kWhatDequeueInputBuffer:
913        {
914            uint32_t replyID;
915            CHECK(msg->senderAwaitsResponse(&replyID));
916
917            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
918                break;
919            }
920
921            int64_t timeoutUs;
922            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
923
924            if (timeoutUs == 0ll) {
925                sp<AMessage> response = new AMessage;
926                response->setInt32("err", -EAGAIN);
927                response->postReply(replyID);
928                break;
929            }
930
931            mFlags |= kFlagDequeueInputPending;
932            mDequeueInputReplyID = replyID;
933
934            if (timeoutUs > 0ll) {
935                sp<AMessage> timeoutMsg =
936                    new AMessage(kWhatDequeueInputTimedOut, id());
937                timeoutMsg->setInt32(
938                        "generation", ++mDequeueInputTimeoutGeneration);
939                timeoutMsg->post(timeoutUs);
940            }
941            break;
942        }
943
944        case kWhatDequeueInputTimedOut:
945        {
946            int32_t generation;
947            CHECK(msg->findInt32("generation", &generation));
948
949            if (generation != mDequeueInputTimeoutGeneration) {
950                // Obsolete
951                break;
952            }
953
954            CHECK(mFlags & kFlagDequeueInputPending);
955
956            sp<AMessage> response = new AMessage;
957            response->setInt32("err", -EAGAIN);
958            response->postReply(mDequeueInputReplyID);
959
960            mFlags &= ~kFlagDequeueInputPending;
961            mDequeueInputReplyID = 0;
962            break;
963        }
964
965        case kWhatQueueInputBuffer:
966        {
967            uint32_t replyID;
968            CHECK(msg->senderAwaitsResponse(&replyID));
969
970            if (mState != STARTED || (mFlags & kFlagStickyError)) {
971                sp<AMessage> response = new AMessage;
972                response->setInt32("err", INVALID_OPERATION);
973
974                response->postReply(replyID);
975                break;
976            }
977
978            status_t err = onQueueInputBuffer(msg);
979
980            sp<AMessage> response = new AMessage;
981            response->setInt32("err", err);
982            response->postReply(replyID);
983            break;
984        }
985
986        case kWhatDequeueOutputBuffer:
987        {
988            uint32_t replyID;
989            CHECK(msg->senderAwaitsResponse(&replyID));
990
991            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
992                break;
993            }
994
995            int64_t timeoutUs;
996            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
997
998            if (timeoutUs == 0ll) {
999                sp<AMessage> response = new AMessage;
1000                response->setInt32("err", -EAGAIN);
1001                response->postReply(replyID);
1002                break;
1003            }
1004
1005            mFlags |= kFlagDequeueOutputPending;
1006            mDequeueOutputReplyID = replyID;
1007
1008            if (timeoutUs > 0ll) {
1009                sp<AMessage> timeoutMsg =
1010                    new AMessage(kWhatDequeueOutputTimedOut, id());
1011                timeoutMsg->setInt32(
1012                        "generation", ++mDequeueOutputTimeoutGeneration);
1013                timeoutMsg->post(timeoutUs);
1014            }
1015            break;
1016        }
1017
1018        case kWhatDequeueOutputTimedOut:
1019        {
1020            int32_t generation;
1021            CHECK(msg->findInt32("generation", &generation));
1022
1023            if (generation != mDequeueOutputTimeoutGeneration) {
1024                // Obsolete
1025                break;
1026            }
1027
1028            CHECK(mFlags & kFlagDequeueOutputPending);
1029
1030            sp<AMessage> response = new AMessage;
1031            response->setInt32("err", -EAGAIN);
1032            response->postReply(mDequeueOutputReplyID);
1033
1034            mFlags &= ~kFlagDequeueOutputPending;
1035            mDequeueOutputReplyID = 0;
1036            break;
1037        }
1038
1039        case kWhatReleaseOutputBuffer:
1040        {
1041            uint32_t replyID;
1042            CHECK(msg->senderAwaitsResponse(&replyID));
1043
1044            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1045                sp<AMessage> response = new AMessage;
1046                response->setInt32("err", INVALID_OPERATION);
1047
1048                response->postReply(replyID);
1049                break;
1050            }
1051
1052            status_t err = onReleaseOutputBuffer(msg);
1053
1054            sp<AMessage> response = new AMessage;
1055            response->setInt32("err", err);
1056            response->postReply(replyID);
1057            break;
1058        }
1059
1060        case kWhatGetBuffers:
1061        {
1062            uint32_t replyID;
1063            CHECK(msg->senderAwaitsResponse(&replyID));
1064
1065            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1066                sp<AMessage> response = new AMessage;
1067                response->setInt32("err", INVALID_OPERATION);
1068
1069                response->postReply(replyID);
1070                break;
1071            }
1072
1073            int32_t portIndex;
1074            CHECK(msg->findInt32("portIndex", &portIndex));
1075
1076            Vector<sp<ABuffer> > *dstBuffers;
1077            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1078
1079            dstBuffers->clear();
1080            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1081
1082            for (size_t i = 0; i < srcBuffers.size(); ++i) {
1083                const BufferInfo &info = srcBuffers.itemAt(i);
1084
1085                dstBuffers->push_back(
1086                        (portIndex == kPortIndexInput && mCrypto != NULL)
1087                                ? info.mEncryptedData : info.mData);
1088            }
1089
1090            (new AMessage)->postReply(replyID);
1091            break;
1092        }
1093
1094        case kWhatFlush:
1095        {
1096            uint32_t replyID;
1097            CHECK(msg->senderAwaitsResponse(&replyID));
1098
1099            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1100                sp<AMessage> response = new AMessage;
1101                response->setInt32("err", INVALID_OPERATION);
1102
1103                response->postReply(replyID);
1104                break;
1105            }
1106
1107            mReplyID = replyID;
1108            setState(FLUSHING);
1109
1110            mCodec->signalFlush();
1111            returnBuffersToCodec();
1112            break;
1113        }
1114
1115        case kWhatGetOutputFormat:
1116        {
1117            uint32_t replyID;
1118            CHECK(msg->senderAwaitsResponse(&replyID));
1119
1120            if ((mState != STARTED && mState != FLUSHING)
1121                    || (mFlags & kFlagStickyError)) {
1122                sp<AMessage> response = new AMessage;
1123                response->setInt32("err", INVALID_OPERATION);
1124
1125                response->postReply(replyID);
1126                break;
1127            }
1128
1129            sp<AMessage> response = new AMessage;
1130            response->setMessage("format", mOutputFormat);
1131            response->postReply(replyID);
1132            break;
1133        }
1134
1135        default:
1136            TRESPASS();
1137    }
1138}
1139
1140void MediaCodec::extractCSD(const sp<AMessage> &format) {
1141    mCSD.clear();
1142
1143    size_t i = 0;
1144    for (;;) {
1145        sp<ABuffer> csd;
1146        if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
1147            break;
1148        }
1149
1150        mCSD.push_back(csd);
1151        ++i;
1152    }
1153
1154    ALOGV("Found %u pieces of codec specific data.", mCSD.size());
1155}
1156
1157status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1158    CHECK(!mCSD.empty());
1159
1160    BufferInfo *info =
1161        &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex);
1162
1163    sp<ABuffer> csd = *mCSD.begin();
1164    mCSD.erase(mCSD.begin());
1165
1166    const sp<ABuffer> &codecInputData =
1167        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1168
1169    if (csd->size() > codecInputData->capacity()) {
1170        return -EINVAL;
1171    }
1172
1173    memcpy(codecInputData->data(), csd->data(), csd->size());
1174
1175    AString errorDetailMsg;
1176
1177    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1178    msg->setSize("index", bufferIndex);
1179    msg->setSize("offset", 0);
1180    msg->setSize("size", csd->size());
1181    msg->setInt64("timeUs", 0ll);
1182    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1183    msg->setPointer("errorDetailMsg", &errorDetailMsg);
1184
1185    return onQueueInputBuffer(msg);
1186}
1187
1188void MediaCodec::setState(State newState) {
1189    if (newState == INITIALIZED || newState == UNINITIALIZED) {
1190        delete mSoftRenderer;
1191        mSoftRenderer = NULL;
1192
1193        mCrypto.clear();
1194        setNativeWindow(NULL);
1195
1196        mOutputFormat.clear();
1197        mFlags &= ~kFlagOutputFormatChanged;
1198        mFlags &= ~kFlagOutputBuffersChanged;
1199        mFlags &= ~kFlagStickyError;
1200    }
1201
1202    mState = newState;
1203
1204    cancelPendingDequeueOperations();
1205}
1206
1207void MediaCodec::returnBuffersToCodec() {
1208    returnBuffersToCodecOnPort(kPortIndexInput);
1209    returnBuffersToCodecOnPort(kPortIndexOutput);
1210}
1211
1212void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1213    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1214
1215    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1216
1217    for (size_t i = 0; i < buffers->size(); ++i) {
1218        BufferInfo *info = &buffers->editItemAt(i);
1219
1220        if (info->mNotify != NULL) {
1221            sp<AMessage> msg = info->mNotify;
1222            info->mNotify = NULL;
1223            info->mOwnedByClient = false;
1224
1225            if (portIndex == kPortIndexInput) {
1226                msg->setInt32("err", ERROR_END_OF_STREAM);
1227            }
1228            msg->post();
1229        }
1230    }
1231
1232    mAvailPortBuffers[portIndex].clear();
1233}
1234
1235size_t MediaCodec::updateBuffers(
1236        int32_t portIndex, const sp<AMessage> &msg) {
1237    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1238
1239    void *bufferID;
1240    CHECK(msg->findPointer("buffer-id", &bufferID));
1241
1242    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1243
1244    for (size_t i = 0; i < buffers->size(); ++i) {
1245        BufferInfo *info = &buffers->editItemAt(i);
1246
1247        if (info->mBufferID == bufferID) {
1248            CHECK(info->mNotify == NULL);
1249            CHECK(msg->findMessage("reply", &info->mNotify));
1250
1251            mAvailPortBuffers[portIndex].push_back(i);
1252
1253            return i;
1254        }
1255    }
1256
1257    TRESPASS();
1258
1259    return 0;
1260}
1261
1262status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1263    size_t index;
1264    size_t offset;
1265    size_t size;
1266    int64_t timeUs;
1267    uint32_t flags;
1268    CHECK(msg->findSize("index", &index));
1269    CHECK(msg->findSize("offset", &offset));
1270    CHECK(msg->findInt64("timeUs", &timeUs));
1271    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1272
1273    const CryptoPlugin::SubSample *subSamples;
1274    size_t numSubSamples;
1275    const uint8_t *key;
1276    const uint8_t *iv;
1277    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1278
1279    // We allow the simpler queueInputBuffer API to be used even in
1280    // secure mode, by fabricating a single unencrypted subSample.
1281    CryptoPlugin::SubSample ss;
1282
1283    if (msg->findSize("size", &size)) {
1284        if (mCrypto != NULL) {
1285            ss.mNumBytesOfClearData = size;
1286            ss.mNumBytesOfEncryptedData = 0;
1287
1288            subSamples = &ss;
1289            numSubSamples = 1;
1290            key = NULL;
1291            iv = NULL;
1292        }
1293    } else {
1294        if (mCrypto == NULL) {
1295            return -EINVAL;
1296        }
1297
1298        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1299        CHECK(msg->findSize("numSubSamples", &numSubSamples));
1300        CHECK(msg->findPointer("key", (void **)&key));
1301        CHECK(msg->findPointer("iv", (void **)&iv));
1302
1303        int32_t tmp;
1304        CHECK(msg->findInt32("mode", &tmp));
1305
1306        mode = (CryptoPlugin::Mode)tmp;
1307
1308        size = 0;
1309        for (size_t i = 0; i < numSubSamples; ++i) {
1310            size += subSamples[i].mNumBytesOfClearData;
1311            size += subSamples[i].mNumBytesOfEncryptedData;
1312        }
1313    }
1314
1315    if (index >= mPortBuffers[kPortIndexInput].size()) {
1316        return -ERANGE;
1317    }
1318
1319    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1320
1321    if (info->mNotify == NULL || !info->mOwnedByClient) {
1322        return -EACCES;
1323    }
1324
1325    if (offset + size > info->mData->capacity()) {
1326        return -EINVAL;
1327    }
1328
1329    sp<AMessage> reply = info->mNotify;
1330    info->mData->setRange(offset, size);
1331    info->mData->meta()->setInt64("timeUs", timeUs);
1332
1333    if (flags & BUFFER_FLAG_EOS) {
1334        info->mData->meta()->setInt32("eos", true);
1335    }
1336
1337    if (flags & BUFFER_FLAG_CODECCONFIG) {
1338        info->mData->meta()->setInt32("csd", true);
1339    }
1340
1341    if (mCrypto != NULL) {
1342        if (size > info->mEncryptedData->capacity()) {
1343            return -ERANGE;
1344        }
1345
1346        AString *errorDetailMsg;
1347        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1348
1349        status_t err = mCrypto->decrypt(
1350                (mFlags & kFlagIsSecure) != 0,
1351                key,
1352                iv,
1353                mode,
1354                info->mEncryptedData->base() + offset,
1355                subSamples,
1356                numSubSamples,
1357                info->mData->base(),
1358                errorDetailMsg);
1359
1360        if (err != OK) {
1361            return err;
1362        }
1363
1364        info->mData->setRange(0, size);
1365    }
1366
1367    reply->setBuffer("buffer", info->mData);
1368    reply->post();
1369
1370    info->mNotify = NULL;
1371    info->mOwnedByClient = false;
1372
1373    return OK;
1374}
1375
1376status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1377    size_t index;
1378    CHECK(msg->findSize("index", &index));
1379
1380    int32_t render;
1381    if (!msg->findInt32("render", &render)) {
1382        render = 0;
1383    }
1384
1385    if (mState != STARTED) {
1386        return -EINVAL;
1387    }
1388
1389    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1390        return -ERANGE;
1391    }
1392
1393    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1394
1395    if (info->mNotify == NULL || !info->mOwnedByClient) {
1396        return -EACCES;
1397    }
1398
1399    if (render) {
1400        info->mNotify->setInt32("render", true);
1401
1402        if (mSoftRenderer != NULL) {
1403            mSoftRenderer->render(
1404                    info->mData->data(), info->mData->size(), NULL);
1405        }
1406    }
1407
1408    info->mNotify->post();
1409    info->mNotify = NULL;
1410    info->mOwnedByClient = false;
1411
1412    return OK;
1413}
1414
1415ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
1416    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1417
1418    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
1419
1420    if (availBuffers->empty()) {
1421        return -EAGAIN;
1422    }
1423
1424    size_t index = *availBuffers->begin();
1425    availBuffers->erase(availBuffers->begin());
1426
1427    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
1428    CHECK(!info->mOwnedByClient);
1429    info->mOwnedByClient = true;
1430
1431    return index;
1432}
1433
1434status_t MediaCodec::setNativeWindow(
1435        const sp<SurfaceTextureClient> &surfaceTextureClient) {
1436    status_t err;
1437
1438    if (mNativeWindow != NULL) {
1439        err = native_window_api_disconnect(
1440                mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
1441
1442        if (err != OK) {
1443            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
1444                    strerror(-err), err);
1445        }
1446
1447        mNativeWindow.clear();
1448    }
1449
1450    if (surfaceTextureClient != NULL) {
1451        err = native_window_api_connect(
1452                surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
1453
1454        if (err != OK) {
1455            ALOGE("native_window_api_connect returned an error: %s (%d)",
1456                    strerror(-err), err);
1457
1458            return err;
1459        }
1460
1461        mNativeWindow = surfaceTextureClient;
1462    }
1463
1464    return OK;
1465}
1466
1467}  // namespace android
1468