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