MediaCodec.cpp revision 5b8987e7de9d04b09153f329c680d2316cdb44ec
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 (mFlags & kFlagDequeueInputPending) {
650                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
651
652                        ++mDequeueInputTimeoutGeneration;
653                        mFlags &= ~kFlagDequeueInputPending;
654                        mDequeueInputReplyID = 0;
655                    }
656                    break;
657                }
658
659                case ACodec::kWhatDrainThisBuffer:
660                {
661                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
662
663                    if (mState == FLUSHING
664                            || mState == STOPPING
665                            || mState == RELEASING) {
666                        returnBuffersToCodecOnPort(kPortIndexOutput);
667                        break;
668                    }
669
670                    sp<ABuffer> buffer;
671                    CHECK(msg->findBuffer("buffer", &buffer));
672
673                    int32_t omxFlags;
674                    CHECK(msg->findInt32("flags", &omxFlags));
675
676                    buffer->meta()->setInt32("omxFlags", omxFlags);
677
678                    if (mFlags & kFlagDequeueOutputPending) {
679                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
680
681                        ++mDequeueOutputTimeoutGeneration;
682                        mFlags &= ~kFlagDequeueOutputPending;
683                        mDequeueOutputReplyID = 0;
684                    }
685                    break;
686                }
687
688                case ACodec::kWhatEOS:
689                {
690                    // We already notify the client of this by using the
691                    // corresponding flag in "onOutputBufferReady".
692                    break;
693                }
694
695                case ACodec::kWhatShutdownCompleted:
696                {
697                    if (mState == STOPPING) {
698                        setState(INITIALIZED);
699                    } else {
700                        CHECK_EQ(mState, RELEASING);
701                        setState(UNINITIALIZED);
702                    }
703
704                    (new AMessage)->postReply(mReplyID);
705                    break;
706                }
707
708                case ACodec::kWhatFlushCompleted:
709                {
710                    CHECK_EQ(mState, FLUSHING);
711                    setState(STARTED);
712
713                    mCodec->signalResume();
714
715                    (new AMessage)->postReply(mReplyID);
716                    break;
717                }
718
719                default:
720                    TRESPASS();
721            }
722            break;
723        }
724
725        case kWhatInit:
726        {
727            uint32_t replyID;
728            CHECK(msg->senderAwaitsResponse(&replyID));
729
730            if (mState != UNINITIALIZED) {
731                sp<AMessage> response = new AMessage;
732                response->setInt32("err", INVALID_OPERATION);
733
734                response->postReply(replyID);
735                break;
736            }
737
738            mReplyID = replyID;
739            setState(INITIALIZING);
740
741            AString name;
742            CHECK(msg->findString("name", &name));
743
744            int32_t nameIsType;
745            int32_t encoder = false;
746            CHECK(msg->findInt32("nameIsType", &nameIsType));
747            if (nameIsType) {
748                CHECK(msg->findInt32("encoder", &encoder));
749            }
750
751            sp<AMessage> format = new AMessage;
752
753            if (nameIsType) {
754                format->setString("mime", name.c_str());
755                format->setInt32("encoder", encoder);
756            } else {
757                format->setString("componentName", name.c_str());
758            }
759
760            mCodec->initiateAllocateComponent(format);
761            break;
762        }
763
764        case kWhatConfigure:
765        {
766            uint32_t replyID;
767            CHECK(msg->senderAwaitsResponse(&replyID));
768
769            if (mState != INITIALIZED) {
770                sp<AMessage> response = new AMessage;
771                response->setInt32("err", INVALID_OPERATION);
772
773                response->postReply(replyID);
774                break;
775            }
776
777            mReplyID = replyID;
778            setState(CONFIGURING);
779
780            sp<RefBase> obj;
781            if (!msg->findObject("native-window", &obj)) {
782                obj.clear();
783            }
784
785            sp<AMessage> format;
786            CHECK(msg->findMessage("format", &format));
787
788            if (obj != NULL) {
789                format->setObject("native-window", obj);
790
791                if (mFlags & kFlagIsSoftwareCodec) {
792                    mNativeWindow =
793                        static_cast<NativeWindowWrapper *>(obj.get())
794                            ->getSurfaceTextureClient();
795                }
796            } else {
797                mNativeWindow.clear();
798            }
799
800            void *crypto;
801            if (!msg->findPointer("crypto", &crypto)) {
802                crypto = NULL;
803            }
804
805            mCrypto = static_cast<ICrypto *>(crypto);
806
807            uint32_t flags;
808            CHECK(msg->findInt32("flags", (int32_t *)&flags));
809
810            if (flags & CONFIGURE_FLAG_ENCODE) {
811                format->setInt32("encoder", true);
812            }
813
814            mCodec->initiateConfigureComponent(format);
815            break;
816        }
817
818        case kWhatStart:
819        {
820            uint32_t replyID;
821            CHECK(msg->senderAwaitsResponse(&replyID));
822
823            if (mState != CONFIGURED) {
824                sp<AMessage> response = new AMessage;
825                response->setInt32("err", INVALID_OPERATION);
826
827                response->postReply(replyID);
828                break;
829            }
830
831            mReplyID = replyID;
832            setState(STARTING);
833
834            mCodec->initiateStart();
835            break;
836        }
837
838        case kWhatStop:
839        {
840            uint32_t replyID;
841            CHECK(msg->senderAwaitsResponse(&replyID));
842
843            if (mState != INITIALIZED
844                    && mState != CONFIGURED && mState != STARTED) {
845                sp<AMessage> response = new AMessage;
846                response->setInt32("err", INVALID_OPERATION);
847
848                response->postReply(replyID);
849                break;
850            }
851
852            mReplyID = replyID;
853            setState(STOPPING);
854
855            mCodec->initiateShutdown(true /* keepComponentAllocated */);
856            returnBuffersToCodec();
857            break;
858        }
859
860        case kWhatRelease:
861        {
862            uint32_t replyID;
863            CHECK(msg->senderAwaitsResponse(&replyID));
864
865            if (mState != INITIALIZED
866                    && mState != CONFIGURED && mState != STARTED) {
867                sp<AMessage> response = new AMessage;
868                response->setInt32("err", INVALID_OPERATION);
869
870                response->postReply(replyID);
871                break;
872            }
873
874            mReplyID = replyID;
875            setState(RELEASING);
876
877            mCodec->initiateShutdown();
878            returnBuffersToCodec();
879            break;
880        }
881
882        case kWhatDequeueInputBuffer:
883        {
884            uint32_t replyID;
885            CHECK(msg->senderAwaitsResponse(&replyID));
886
887            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
888                break;
889            }
890
891            int64_t timeoutUs;
892            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
893
894            if (timeoutUs == 0ll) {
895                sp<AMessage> response = new AMessage;
896                response->setInt32("err", -EAGAIN);
897                response->postReply(replyID);
898                break;
899            }
900
901            mFlags |= kFlagDequeueInputPending;
902            mDequeueInputReplyID = replyID;
903
904            if (timeoutUs > 0ll) {
905                sp<AMessage> timeoutMsg =
906                    new AMessage(kWhatDequeueInputTimedOut, id());
907                timeoutMsg->setInt32(
908                        "generation", ++mDequeueInputTimeoutGeneration);
909                timeoutMsg->post(timeoutUs);
910            }
911            break;
912        }
913
914        case kWhatDequeueInputTimedOut:
915        {
916            int32_t generation;
917            CHECK(msg->findInt32("generation", &generation));
918
919            if (generation != mDequeueInputTimeoutGeneration) {
920                // Obsolete
921                break;
922            }
923
924            CHECK(mFlags & kFlagDequeueInputPending);
925
926            sp<AMessage> response = new AMessage;
927            response->setInt32("err", -EAGAIN);
928            response->postReply(mDequeueInputReplyID);
929
930            mFlags &= ~kFlagDequeueInputPending;
931            mDequeueInputReplyID = 0;
932            break;
933        }
934
935        case kWhatQueueInputBuffer:
936        {
937            uint32_t replyID;
938            CHECK(msg->senderAwaitsResponse(&replyID));
939
940            if (mState != STARTED || (mFlags & kFlagStickyError)) {
941                sp<AMessage> response = new AMessage;
942                response->setInt32("err", INVALID_OPERATION);
943
944                response->postReply(replyID);
945                break;
946            }
947
948            status_t err = onQueueInputBuffer(msg);
949
950            sp<AMessage> response = new AMessage;
951            response->setInt32("err", err);
952            response->postReply(replyID);
953            break;
954        }
955
956        case kWhatDequeueOutputBuffer:
957        {
958            uint32_t replyID;
959            CHECK(msg->senderAwaitsResponse(&replyID));
960
961            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
962                break;
963            }
964
965            int64_t timeoutUs;
966            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
967
968            if (timeoutUs == 0ll) {
969                sp<AMessage> response = new AMessage;
970                response->setInt32("err", -EAGAIN);
971                response->postReply(replyID);
972                break;
973            }
974
975            mFlags |= kFlagDequeueOutputPending;
976            mDequeueOutputReplyID = replyID;
977
978            if (timeoutUs > 0ll) {
979                sp<AMessage> timeoutMsg =
980                    new AMessage(kWhatDequeueOutputTimedOut, id());
981                timeoutMsg->setInt32(
982                        "generation", ++mDequeueOutputTimeoutGeneration);
983                timeoutMsg->post(timeoutUs);
984            }
985            break;
986        }
987
988        case kWhatDequeueOutputTimedOut:
989        {
990            int32_t generation;
991            CHECK(msg->findInt32("generation", &generation));
992
993            if (generation != mDequeueOutputTimeoutGeneration) {
994                // Obsolete
995                break;
996            }
997
998            CHECK(mFlags & kFlagDequeueOutputPending);
999
1000            sp<AMessage> response = new AMessage;
1001            response->setInt32("err", -EAGAIN);
1002            response->postReply(mDequeueOutputReplyID);
1003
1004            mFlags &= ~kFlagDequeueOutputPending;
1005            mDequeueOutputReplyID = 0;
1006            break;
1007        }
1008
1009        case kWhatReleaseOutputBuffer:
1010        {
1011            uint32_t replyID;
1012            CHECK(msg->senderAwaitsResponse(&replyID));
1013
1014            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1015                sp<AMessage> response = new AMessage;
1016                response->setInt32("err", INVALID_OPERATION);
1017
1018                response->postReply(replyID);
1019                break;
1020            }
1021
1022            status_t err = onReleaseOutputBuffer(msg);
1023
1024            sp<AMessage> response = new AMessage;
1025            response->setInt32("err", err);
1026            response->postReply(replyID);
1027            break;
1028        }
1029
1030        case kWhatGetBuffers:
1031        {
1032            uint32_t replyID;
1033            CHECK(msg->senderAwaitsResponse(&replyID));
1034
1035            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1036                sp<AMessage> response = new AMessage;
1037                response->setInt32("err", INVALID_OPERATION);
1038
1039                response->postReply(replyID);
1040                break;
1041            }
1042
1043            int32_t portIndex;
1044            CHECK(msg->findInt32("portIndex", &portIndex));
1045
1046            Vector<sp<ABuffer> > *dstBuffers;
1047            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1048
1049            dstBuffers->clear();
1050            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1051
1052            for (size_t i = 0; i < srcBuffers.size(); ++i) {
1053                const BufferInfo &info = srcBuffers.itemAt(i);
1054
1055                dstBuffers->push_back(
1056                        (portIndex == kPortIndexInput && mCrypto != NULL)
1057                                ? info.mEncryptedData : info.mData);
1058            }
1059
1060            (new AMessage)->postReply(replyID);
1061            break;
1062        }
1063
1064        case kWhatFlush:
1065        {
1066            uint32_t replyID;
1067            CHECK(msg->senderAwaitsResponse(&replyID));
1068
1069            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1070                sp<AMessage> response = new AMessage;
1071                response->setInt32("err", INVALID_OPERATION);
1072
1073                response->postReply(replyID);
1074                break;
1075            }
1076
1077            mReplyID = replyID;
1078            setState(FLUSHING);
1079
1080            mCodec->signalFlush();
1081            returnBuffersToCodec();
1082            break;
1083        }
1084
1085        case kWhatGetOutputFormat:
1086        {
1087            uint32_t replyID;
1088            CHECK(msg->senderAwaitsResponse(&replyID));
1089
1090            if ((mState != STARTED && mState != FLUSHING)
1091                    || (mFlags & kFlagStickyError)) {
1092                sp<AMessage> response = new AMessage;
1093                response->setInt32("err", INVALID_OPERATION);
1094
1095                response->postReply(replyID);
1096                break;
1097            }
1098
1099            sp<AMessage> response = new AMessage;
1100            response->setMessage("format", mOutputFormat);
1101            response->postReply(replyID);
1102            break;
1103        }
1104
1105        default:
1106            TRESPASS();
1107    }
1108}
1109
1110void MediaCodec::setState(State newState) {
1111    if (newState == INITIALIZED) {
1112        delete mSoftRenderer;
1113        mSoftRenderer = NULL;
1114
1115        mCrypto.clear();
1116        mNativeWindow.clear();
1117
1118        mOutputFormat.clear();
1119        mFlags &= ~kFlagOutputFormatChanged;
1120        mFlags &= ~kFlagOutputBuffersChanged;
1121        mFlags &= ~kFlagStickyError;
1122    }
1123
1124    mState = newState;
1125
1126    cancelPendingDequeueOperations();
1127}
1128
1129void MediaCodec::returnBuffersToCodec() {
1130    returnBuffersToCodecOnPort(kPortIndexInput);
1131    returnBuffersToCodecOnPort(kPortIndexOutput);
1132}
1133
1134void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1135    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1136
1137    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1138
1139    for (size_t i = 0; i < buffers->size(); ++i) {
1140        BufferInfo *info = &buffers->editItemAt(i);
1141
1142        if (info->mNotify != NULL) {
1143            sp<AMessage> msg = info->mNotify;
1144            info->mNotify = NULL;
1145            info->mOwnedByClient = false;
1146
1147            if (portIndex == kPortIndexInput) {
1148                msg->setInt32("err", ERROR_END_OF_STREAM);
1149            }
1150            msg->post();
1151        }
1152    }
1153
1154    mAvailPortBuffers[portIndex].clear();
1155}
1156
1157size_t MediaCodec::updateBuffers(
1158        int32_t portIndex, const sp<AMessage> &msg) {
1159    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1160
1161    void *bufferID;
1162    CHECK(msg->findPointer("buffer-id", &bufferID));
1163
1164    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1165
1166    for (size_t i = 0; i < buffers->size(); ++i) {
1167        BufferInfo *info = &buffers->editItemAt(i);
1168
1169        if (info->mBufferID == bufferID) {
1170            CHECK(info->mNotify == NULL);
1171            CHECK(msg->findMessage("reply", &info->mNotify));
1172
1173            mAvailPortBuffers[portIndex].push_back(i);
1174
1175            return i;
1176        }
1177    }
1178
1179    TRESPASS();
1180
1181    return 0;
1182}
1183
1184status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1185    size_t index;
1186    size_t offset;
1187    size_t size;
1188    int64_t timeUs;
1189    uint32_t flags;
1190    CHECK(msg->findSize("index", &index));
1191    CHECK(msg->findSize("offset", &offset));
1192    CHECK(msg->findInt64("timeUs", &timeUs));
1193    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1194
1195    const CryptoPlugin::SubSample *subSamples;
1196    size_t numSubSamples;
1197    const uint8_t *key;
1198    const uint8_t *iv;
1199    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1200
1201    // We allow the simpler queueInputBuffer API to be used even in
1202    // secure mode, by fabricating a single unencrypted subSample.
1203    CryptoPlugin::SubSample ss;
1204
1205    if (msg->findSize("size", &size)) {
1206        if (mCrypto != NULL) {
1207            ss.mNumBytesOfClearData = size;
1208            ss.mNumBytesOfEncryptedData = 0;
1209
1210            subSamples = &ss;
1211            numSubSamples = 1;
1212            key = NULL;
1213            iv = NULL;
1214        }
1215    } else {
1216        if (mCrypto == NULL) {
1217            return -EINVAL;
1218        }
1219
1220        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1221        CHECK(msg->findSize("numSubSamples", &numSubSamples));
1222        CHECK(msg->findPointer("key", (void **)&key));
1223        CHECK(msg->findPointer("iv", (void **)&iv));
1224
1225        int32_t tmp;
1226        CHECK(msg->findInt32("mode", &tmp));
1227
1228        mode = (CryptoPlugin::Mode)tmp;
1229
1230        size = 0;
1231        for (size_t i = 0; i < numSubSamples; ++i) {
1232            size += subSamples[i].mNumBytesOfClearData;
1233            size += subSamples[i].mNumBytesOfEncryptedData;
1234        }
1235    }
1236
1237    if (index >= mPortBuffers[kPortIndexInput].size()) {
1238        return -ERANGE;
1239    }
1240
1241    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1242
1243    if (info->mNotify == NULL || !info->mOwnedByClient) {
1244        return -EACCES;
1245    }
1246
1247    if (offset + size > info->mData->capacity()) {
1248        return -EINVAL;
1249    }
1250
1251    sp<AMessage> reply = info->mNotify;
1252    info->mData->setRange(offset, size);
1253    info->mData->meta()->setInt64("timeUs", timeUs);
1254
1255    if (flags & BUFFER_FLAG_EOS) {
1256        info->mData->meta()->setInt32("eos", true);
1257    }
1258
1259    if (flags & BUFFER_FLAG_CODECCONFIG) {
1260        info->mData->meta()->setInt32("csd", true);
1261    }
1262
1263    if (mCrypto != NULL) {
1264        if (size > info->mEncryptedData->capacity()) {
1265            return -ERANGE;
1266        }
1267
1268        AString *errorDetailMsg;
1269        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1270
1271        status_t err = mCrypto->decrypt(
1272                (mFlags & kFlagIsSecure) != 0,
1273                key,
1274                iv,
1275                mode,
1276                info->mEncryptedData->base() + offset,
1277                subSamples,
1278                numSubSamples,
1279                info->mData->base(),
1280                errorDetailMsg);
1281
1282        if (err != OK) {
1283            return err;
1284        }
1285
1286        info->mData->setRange(0, size);
1287    }
1288
1289    reply->setBuffer("buffer", info->mData);
1290    reply->post();
1291
1292    info->mNotify = NULL;
1293    info->mOwnedByClient = false;
1294
1295    return OK;
1296}
1297
1298status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1299    size_t index;
1300    CHECK(msg->findSize("index", &index));
1301
1302    int32_t render;
1303    if (!msg->findInt32("render", &render)) {
1304        render = 0;
1305    }
1306
1307    if (mState != STARTED) {
1308        return -EINVAL;
1309    }
1310
1311    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1312        return -ERANGE;
1313    }
1314
1315    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1316
1317    if (info->mNotify == NULL || !info->mOwnedByClient) {
1318        return -EACCES;
1319    }
1320
1321    if (render) {
1322        info->mNotify->setInt32("render", true);
1323
1324        if (mSoftRenderer != NULL) {
1325            mSoftRenderer->render(
1326                    info->mData->data(), info->mData->size(), NULL);
1327        }
1328    }
1329
1330    info->mNotify->post();
1331    info->mNotify = NULL;
1332    info->mOwnedByClient = false;
1333
1334    return OK;
1335}
1336
1337ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
1338    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1339
1340    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
1341
1342    if (availBuffers->empty()) {
1343        return -EAGAIN;
1344    }
1345
1346    size_t index = *availBuffers->begin();
1347    availBuffers->erase(availBuffers->begin());
1348
1349    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
1350    CHECK(!info->mOwnedByClient);
1351    info->mOwnedByClient = true;
1352
1353    return index;
1354}
1355
1356}  // namespace android
1357