MediaCodec.cpp revision 3a01a71dcbb467d06cc5da4a72a82bb588648cfc
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 <inttypes.h>
20
21#include "include/avc_utils.h"
22#include "include/SoftwareRenderer.h"
23
24#include <binder/IBatteryStats.h>
25#include <binder/IServiceManager.h>
26#include <gui/Surface.h>
27#include <media/ICrypto.h>
28#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
31#include <media/stagefright/foundation/AString.h>
32#include <media/stagefright/foundation/hexdump.h>
33#include <media/stagefright/ACodec.h>
34#include <media/stagefright/BufferProducerWrapper.h>
35#include <media/stagefright/MediaCodec.h>
36#include <media/stagefright/MediaCodecList.h>
37#include <media/stagefright/MediaDefs.h>
38#include <media/stagefright/MediaErrors.h>
39#include <media/stagefright/MetaData.h>
40#include <media/stagefright/NativeWindowWrapper.h>
41#include <private/android_filesystem_config.h>
42#include <utils/Log.h>
43#include <utils/Singleton.h>
44
45namespace android {
46
47struct MediaCodec::BatteryNotifier : public Singleton<BatteryNotifier> {
48    BatteryNotifier();
49
50    void noteStartVideo();
51    void noteStopVideo();
52    void noteStartAudio();
53    void noteStopAudio();
54
55private:
56    int32_t mVideoRefCount;
57    int32_t mAudioRefCount;
58    sp<IBatteryStats> mBatteryStatService;
59};
60
61ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier)
62
63MediaCodec::BatteryNotifier::BatteryNotifier() :
64    mVideoRefCount(0),
65    mAudioRefCount(0) {
66    // get battery service
67    const sp<IServiceManager> sm(defaultServiceManager());
68    if (sm != NULL) {
69        const String16 name("batterystats");
70        mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));
71        if (mBatteryStatService == NULL) {
72            ALOGE("batterystats service unavailable!");
73        }
74    }
75}
76
77void MediaCodec::BatteryNotifier::noteStartVideo() {
78    if (mVideoRefCount == 0 && mBatteryStatService != NULL) {
79        mBatteryStatService->noteStartVideo(AID_MEDIA);
80    }
81    mVideoRefCount++;
82}
83
84void MediaCodec::BatteryNotifier::noteStopVideo() {
85    if (mVideoRefCount == 0) {
86        ALOGW("BatteryNotifier::noteStop(): video refcount is broken!");
87        return;
88    }
89
90    mVideoRefCount--;
91    if (mVideoRefCount == 0 && mBatteryStatService != NULL) {
92        mBatteryStatService->noteStopVideo(AID_MEDIA);
93    }
94}
95
96void MediaCodec::BatteryNotifier::noteStartAudio() {
97    if (mAudioRefCount == 0 && mBatteryStatService != NULL) {
98        mBatteryStatService->noteStartAudio(AID_MEDIA);
99    }
100    mAudioRefCount++;
101}
102
103void MediaCodec::BatteryNotifier::noteStopAudio() {
104    if (mAudioRefCount == 0) {
105        ALOGW("BatteryNotifier::noteStop(): audio refcount is broken!");
106        return;
107    }
108
109    mAudioRefCount--;
110    if (mAudioRefCount == 0 && mBatteryStatService != NULL) {
111        mBatteryStatService->noteStopAudio(AID_MEDIA);
112    }
113}
114// static
115sp<MediaCodec> MediaCodec::CreateByType(
116        const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err) {
117    sp<MediaCodec> codec = new MediaCodec(looper);
118
119    const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
120    if (err != NULL) {
121        *err = ret;
122    }
123    return ret == OK ? codec : NULL; // NULL deallocates codec.
124}
125
126// static
127sp<MediaCodec> MediaCodec::CreateByComponentName(
128        const sp<ALooper> &looper, const char *name, status_t *err) {
129    sp<MediaCodec> codec = new MediaCodec(looper);
130
131    const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
132    if (err != NULL) {
133        *err = ret;
134    }
135    return ret == OK ? codec : NULL; // NULL deallocates codec.
136}
137
138MediaCodec::MediaCodec(const sp<ALooper> &looper)
139    : mState(UNINITIALIZED),
140      mLooper(looper),
141      mCodec(NULL),
142      mReplyID(0),
143      mFlags(0),
144      mStickyError(OK),
145      mSoftRenderer(NULL),
146      mBatteryStatNotified(false),
147      mIsVideo(false),
148      mDequeueInputTimeoutGeneration(0),
149      mDequeueInputReplyID(0),
150      mDequeueOutputTimeoutGeneration(0),
151      mDequeueOutputReplyID(0),
152      mHaveInputSurface(false) {
153}
154
155MediaCodec::~MediaCodec() {
156    CHECK_EQ(mState, UNINITIALIZED);
157}
158
159// static
160status_t MediaCodec::PostAndAwaitResponse(
161        const sp<AMessage> &msg, sp<AMessage> *response) {
162    status_t err = msg->postAndAwaitResponse(response);
163
164    if (err != OK) {
165        return err;
166    }
167
168    if (!(*response)->findInt32("err", &err)) {
169        err = OK;
170    }
171
172    return err;
173}
174
175// static
176void MediaCodec::PostReplyWithError(int32_t replyID, int32_t err) {
177    sp<AMessage> response = new AMessage;
178    response->setInt32("err", err);
179    response->postReply(replyID);
180}
181
182status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
183    // save init parameters for reset
184    mInitName = name;
185    mInitNameIsType = nameIsType;
186    mInitIsEncoder = encoder;
187
188    // Current video decoders do not return from OMX_FillThisBuffer
189    // quickly, violating the OpenMAX specs, until that is remedied
190    // we need to invest in an extra looper to free the main event
191    // queue.
192    mCodec = new ACodec;
193    bool needDedicatedLooper = false;
194    if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
195        needDedicatedLooper = true;
196    } else {
197        AString tmp = name;
198        if (tmp.endsWith(".secure")) {
199            tmp.erase(tmp.size() - 7, 7);
200        }
201        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
202        ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
203        if (codecIdx >= 0) {
204            const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
205            Vector<AString> mimes;
206            info->getSupportedMimes(&mimes);
207            for (size_t i = 0; i < mimes.size(); i++) {
208                if (mimes[i].startsWith("video/")) {
209                    needDedicatedLooper = true;
210                    break;
211                }
212            }
213        }
214    }
215
216    if (needDedicatedLooper) {
217        if (mCodecLooper == NULL) {
218            mCodecLooper = new ALooper;
219            mCodecLooper->setName("CodecLooper");
220            mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
221        }
222
223        mCodecLooper->registerHandler(mCodec);
224    } else {
225        mLooper->registerHandler(mCodec);
226    }
227
228    mLooper->registerHandler(this);
229
230    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
231
232    sp<AMessage> msg = new AMessage(kWhatInit, id());
233    msg->setString("name", name);
234    msg->setInt32("nameIsType", nameIsType);
235
236    if (nameIsType) {
237        msg->setInt32("encoder", encoder);
238    }
239
240    sp<AMessage> response;
241    return PostAndAwaitResponse(msg, &response);
242}
243
244status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
245    sp<AMessage> msg = new AMessage(kWhatSetCallback, id());
246    msg->setMessage("callback", callback);
247
248    sp<AMessage> response;
249    return PostAndAwaitResponse(msg, &response);
250}
251
252status_t MediaCodec::configure(
253        const sp<AMessage> &format,
254        const sp<Surface> &nativeWindow,
255        const sp<ICrypto> &crypto,
256        uint32_t flags) {
257    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
258
259    msg->setMessage("format", format);
260    msg->setInt32("flags", flags);
261
262    if (nativeWindow != NULL) {
263        msg->setObject(
264                "native-window",
265                new NativeWindowWrapper(nativeWindow));
266    }
267
268    if (crypto != NULL) {
269        msg->setPointer("crypto", crypto.get());
270    }
271
272    sp<AMessage> response;
273    status_t err = PostAndAwaitResponse(msg, &response);
274
275    if (err != OK && err != INVALID_OPERATION) {
276        // MediaCodec now set state to UNINITIALIZED upon any fatal error.
277        // To maintain backward-compatibility, do a reset() to put codec
278        // back into INITIALIZED state.
279        // But don't reset if the err is INVALID_OPERATION, which means
280        // the configure failure is due to wrong state.
281
282        ALOGE("configure failed with err 0x%08x, resetting...", err);
283        reset();
284    }
285
286    return err;
287}
288
289status_t MediaCodec::createInputSurface(
290        sp<IGraphicBufferProducer>* bufferProducer) {
291    sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id());
292
293    sp<AMessage> response;
294    status_t err = PostAndAwaitResponse(msg, &response);
295    if (err == NO_ERROR) {
296        // unwrap the sp<IGraphicBufferProducer>
297        sp<RefBase> obj;
298        bool found = response->findObject("input-surface", &obj);
299        CHECK(found);
300        sp<BufferProducerWrapper> wrapper(
301                static_cast<BufferProducerWrapper*>(obj.get()));
302        *bufferProducer = wrapper->getBufferProducer();
303    } else {
304        ALOGW("createInputSurface failed, err=%d", err);
305    }
306    return err;
307}
308
309status_t MediaCodec::start() {
310    sp<AMessage> msg = new AMessage(kWhatStart, id());
311
312    sp<AMessage> response;
313    return PostAndAwaitResponse(msg, &response);
314}
315
316status_t MediaCodec::stop() {
317    sp<AMessage> msg = new AMessage(kWhatStop, id());
318
319    sp<AMessage> response;
320    return PostAndAwaitResponse(msg, &response);
321}
322
323status_t MediaCodec::release() {
324    sp<AMessage> msg = new AMessage(kWhatRelease, id());
325
326    sp<AMessage> response;
327    return PostAndAwaitResponse(msg, &response);
328}
329
330status_t MediaCodec::reset() {
331    /* When external-facing MediaCodec object is created,
332       it is already initialized.  Thus, reset is essentially
333       release() followed by init(), plus clearing the state */
334
335    status_t err = release();
336
337    // unregister handlers
338    if (mCodec != NULL) {
339        if (mCodecLooper != NULL) {
340            mCodecLooper->unregisterHandler(mCodec->id());
341        } else {
342            mLooper->unregisterHandler(mCodec->id());
343        }
344        mCodec = NULL;
345    }
346    mLooper->unregisterHandler(id());
347
348    mFlags = 0;    // clear all flags
349    mStickyError = OK;
350
351    // reset state not reset by setState(UNINITIALIZED)
352    mReplyID = 0;
353    mDequeueInputReplyID = 0;
354    mDequeueOutputReplyID = 0;
355    mDequeueInputTimeoutGeneration = 0;
356    mDequeueOutputTimeoutGeneration = 0;
357    mHaveInputSurface = false;
358
359    if (err == OK) {
360        err = init(mInitName, mInitNameIsType, mInitIsEncoder);
361    }
362    return err;
363}
364
365status_t MediaCodec::queueInputBuffer(
366        size_t index,
367        size_t offset,
368        size_t size,
369        int64_t presentationTimeUs,
370        uint32_t flags,
371        AString *errorDetailMsg) {
372    if (errorDetailMsg != NULL) {
373        errorDetailMsg->clear();
374    }
375
376    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
377    msg->setSize("index", index);
378    msg->setSize("offset", offset);
379    msg->setSize("size", size);
380    msg->setInt64("timeUs", presentationTimeUs);
381    msg->setInt32("flags", flags);
382    msg->setPointer("errorDetailMsg", errorDetailMsg);
383
384    sp<AMessage> response;
385    return PostAndAwaitResponse(msg, &response);
386}
387
388status_t MediaCodec::queueSecureInputBuffer(
389        size_t index,
390        size_t offset,
391        const CryptoPlugin::SubSample *subSamples,
392        size_t numSubSamples,
393        const uint8_t key[16],
394        const uint8_t iv[16],
395        CryptoPlugin::Mode mode,
396        int64_t presentationTimeUs,
397        uint32_t flags,
398        AString *errorDetailMsg) {
399    if (errorDetailMsg != NULL) {
400        errorDetailMsg->clear();
401    }
402
403    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
404    msg->setSize("index", index);
405    msg->setSize("offset", offset);
406    msg->setPointer("subSamples", (void *)subSamples);
407    msg->setSize("numSubSamples", numSubSamples);
408    msg->setPointer("key", (void *)key);
409    msg->setPointer("iv", (void *)iv);
410    msg->setInt32("mode", mode);
411    msg->setInt64("timeUs", presentationTimeUs);
412    msg->setInt32("flags", flags);
413    msg->setPointer("errorDetailMsg", errorDetailMsg);
414
415    sp<AMessage> response;
416    status_t err = PostAndAwaitResponse(msg, &response);
417
418    return err;
419}
420
421status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
422    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
423    msg->setInt64("timeoutUs", timeoutUs);
424
425    sp<AMessage> response;
426    status_t err;
427    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
428        return err;
429    }
430
431    CHECK(response->findSize("index", index));
432
433    return OK;
434}
435
436status_t MediaCodec::dequeueOutputBuffer(
437        size_t *index,
438        size_t *offset,
439        size_t *size,
440        int64_t *presentationTimeUs,
441        uint32_t *flags,
442        int64_t timeoutUs) {
443    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
444    msg->setInt64("timeoutUs", timeoutUs);
445
446    sp<AMessage> response;
447    status_t err;
448    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
449        return err;
450    }
451
452    CHECK(response->findSize("index", index));
453    CHECK(response->findSize("offset", offset));
454    CHECK(response->findSize("size", size));
455    CHECK(response->findInt64("timeUs", presentationTimeUs));
456    CHECK(response->findInt32("flags", (int32_t *)flags));
457
458    return OK;
459}
460
461status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
462    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
463    msg->setSize("index", index);
464    msg->setInt32("render", true);
465
466    sp<AMessage> response;
467    return PostAndAwaitResponse(msg, &response);
468}
469
470status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
471    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
472    msg->setSize("index", index);
473    msg->setInt32("render", true);
474    msg->setInt64("timestampNs", timestampNs);
475
476    sp<AMessage> response;
477    return PostAndAwaitResponse(msg, &response);
478}
479
480status_t MediaCodec::releaseOutputBuffer(size_t index) {
481    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
482    msg->setSize("index", index);
483
484    sp<AMessage> response;
485    return PostAndAwaitResponse(msg, &response);
486}
487
488status_t MediaCodec::signalEndOfInputStream() {
489    sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id());
490
491    sp<AMessage> response;
492    return PostAndAwaitResponse(msg, &response);
493}
494
495status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
496    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
497
498    sp<AMessage> response;
499    status_t err;
500    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
501        return err;
502    }
503
504    CHECK(response->findMessage("format", format));
505
506    return OK;
507}
508
509status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
510    sp<AMessage> msg = new AMessage(kWhatGetInputFormat, id());
511
512    sp<AMessage> response;
513    status_t err;
514    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
515        return err;
516    }
517
518    CHECK(response->findMessage("format", format));
519
520    return OK;
521}
522
523status_t MediaCodec::getName(AString *name) const {
524    sp<AMessage> msg = new AMessage(kWhatGetName, id());
525
526    sp<AMessage> response;
527    status_t err;
528    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
529        return err;
530    }
531
532    CHECK(response->findString("name", name));
533
534    return OK;
535}
536
537status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
538    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
539    msg->setInt32("portIndex", kPortIndexInput);
540    msg->setPointer("buffers", buffers);
541
542    sp<AMessage> response;
543    return PostAndAwaitResponse(msg, &response);
544}
545
546status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
547    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
548    msg->setInt32("portIndex", kPortIndexOutput);
549    msg->setPointer("buffers", buffers);
550
551    sp<AMessage> response;
552    return PostAndAwaitResponse(msg, &response);
553}
554
555status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
556    sp<AMessage> format;
557    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
558}
559
560status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
561    sp<ABuffer> buffer;
562    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
563}
564
565status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
566    sp<AMessage> format;
567    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
568}
569
570bool MediaCodec::isExecuting() const {
571    return mState == STARTED || mState == FLUSHED;
572}
573
574status_t MediaCodec::getBufferAndFormat(
575        size_t portIndex, size_t index,
576        sp<ABuffer> *buffer, sp<AMessage> *format) {
577    // use mutex instead of a context switch
578
579    buffer->clear();
580    format->clear();
581    if (!isExecuting()) {
582        return INVALID_OPERATION;
583    }
584
585    // we do not want mPortBuffers to change during this section
586    // we also don't want mOwnedByClient to change during this
587    Mutex::Autolock al(mBufferLock);
588    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
589    if (index < buffers->size()) {
590        const BufferInfo &info = buffers->itemAt(index);
591        if (info.mOwnedByClient) {
592            // by the time buffers array is initialized, crypto is set
593            if (portIndex == kPortIndexInput && mCrypto != NULL) {
594                *buffer = info.mEncryptedData;
595            } else {
596                *buffer = info.mData;
597            }
598            *format = info.mFormat;
599        }
600    }
601    return OK;
602}
603
604status_t MediaCodec::flush() {
605    sp<AMessage> msg = new AMessage(kWhatFlush, id());
606
607    sp<AMessage> response;
608    return PostAndAwaitResponse(msg, &response);
609}
610
611status_t MediaCodec::requestIDRFrame() {
612    (new AMessage(kWhatRequestIDRFrame, id()))->post();
613
614    return OK;
615}
616
617void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
618    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
619    msg->setMessage("notify", notify);
620    msg->post();
621}
622
623////////////////////////////////////////////////////////////////////////////////
624
625void MediaCodec::cancelPendingDequeueOperations() {
626    if (mFlags & kFlagDequeueInputPending) {
627        PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
628
629        ++mDequeueInputTimeoutGeneration;
630        mDequeueInputReplyID = 0;
631        mFlags &= ~kFlagDequeueInputPending;
632    }
633
634    if (mFlags & kFlagDequeueOutputPending) {
635        PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
636
637        ++mDequeueOutputTimeoutGeneration;
638        mDequeueOutputReplyID = 0;
639        mFlags &= ~kFlagDequeueOutputPending;
640    }
641}
642
643bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
644    if (!isExecuting() || (mFlags & kFlagIsAsync)
645            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
646        PostReplyWithError(replyID, INVALID_OPERATION);
647        return true;
648    } else if (mFlags & kFlagStickyError) {
649        PostReplyWithError(replyID, getStickyError());
650        return true;
651    }
652
653    ssize_t index = dequeuePortBuffer(kPortIndexInput);
654
655    if (index < 0) {
656        CHECK_EQ(index, -EAGAIN);
657        return false;
658    }
659
660    sp<AMessage> response = new AMessage;
661    response->setSize("index", index);
662    response->postReply(replyID);
663
664    return true;
665}
666
667bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
668    sp<AMessage> response = new AMessage;
669
670    if (!isExecuting() || (mFlags & kFlagIsAsync)
671            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
672        response->setInt32("err", INVALID_OPERATION);
673    } else if (mFlags & kFlagStickyError) {
674        response->setInt32("err", getStickyError());
675    } else if (mFlags & kFlagOutputBuffersChanged) {
676        response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
677        mFlags &= ~kFlagOutputBuffersChanged;
678    } else if (mFlags & kFlagOutputFormatChanged) {
679        response->setInt32("err", INFO_FORMAT_CHANGED);
680        mFlags &= ~kFlagOutputFormatChanged;
681    } else {
682        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
683
684        if (index < 0) {
685            CHECK_EQ(index, -EAGAIN);
686            return false;
687        }
688
689        const sp<ABuffer> &buffer =
690            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
691
692        response->setSize("index", index);
693        response->setSize("offset", buffer->offset());
694        response->setSize("size", buffer->size());
695
696        int64_t timeUs;
697        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
698
699        response->setInt64("timeUs", timeUs);
700
701        int32_t omxFlags;
702        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
703
704        uint32_t flags = 0;
705        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
706            flags |= BUFFER_FLAG_SYNCFRAME;
707        }
708        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
709            flags |= BUFFER_FLAG_CODECCONFIG;
710        }
711        if (omxFlags & OMX_BUFFERFLAG_EOS) {
712            flags |= BUFFER_FLAG_EOS;
713        }
714
715        response->setInt32("flags", flags);
716    }
717
718    response->postReply(replyID);
719
720    return true;
721}
722
723void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
724    switch (msg->what()) {
725        case kWhatCodecNotify:
726        {
727            int32_t what;
728            CHECK(msg->findInt32("what", &what));
729
730            switch (what) {
731                case CodecBase::kWhatError:
732                {
733                    int32_t err, actionCode;
734                    CHECK(msg->findInt32("err", &err));
735                    CHECK(msg->findInt32("actionCode", &actionCode));
736
737                    ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
738                            err, actionCode, mState);
739                    if (err == DEAD_OBJECT) {
740                        mFlags |= kFlagSawMediaServerDie;
741                        mFlags &= ~kFlagIsComponentAllocated;
742                    }
743
744                    bool sendErrorResponse = true;
745
746                    switch (mState) {
747                        case INITIALIZING:
748                        {
749                            setState(UNINITIALIZED);
750                            break;
751                        }
752
753                        case CONFIGURING:
754                        {
755                            setState(actionCode == ACTION_CODE_FATAL ?
756                                    UNINITIALIZED : INITIALIZED);
757                            break;
758                        }
759
760                        case STARTING:
761                        {
762                            setState(actionCode == ACTION_CODE_FATAL ?
763                                    UNINITIALIZED : CONFIGURED);
764                            break;
765                        }
766
767                        case STOPPING:
768                        case RELEASING:
769                        {
770                            // Ignore the error, assuming we'll still get
771                            // the shutdown complete notification.
772
773                            sendErrorResponse = false;
774
775                            if (mFlags & kFlagSawMediaServerDie) {
776                                // MediaServer died, there definitely won't
777                                // be a shutdown complete notification after
778                                // all.
779
780                                // note that we're directly going from
781                                // STOPPING->UNINITIALIZED, instead of the
782                                // usual STOPPING->INITIALIZED state.
783                                setState(UNINITIALIZED);
784                                if (mState == RELEASING) {
785                                    mComponentName.clear();
786                                }
787                                (new AMessage)->postReply(mReplyID);
788                            }
789                            break;
790                        }
791
792                        case FLUSHING:
793                        {
794                            if (actionCode == ACTION_CODE_FATAL) {
795                                setState(UNINITIALIZED);
796                            } else {
797                                setState(
798                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
799                            }
800                            break;
801                        }
802
803                        case FLUSHED:
804                        case STARTED:
805                        {
806                            sendErrorResponse = false;
807
808                            setStickyError(err);
809                            postActivityNotificationIfPossible();
810
811                            cancelPendingDequeueOperations();
812
813                            if (mFlags & kFlagIsAsync) {
814                                onError(err, actionCode);
815                            }
816                            switch (actionCode) {
817                            case ACTION_CODE_TRANSIENT:
818                                break;
819                            case ACTION_CODE_RECOVERABLE:
820                                setState(INITIALIZED);
821                                break;
822                            default:
823                                setState(UNINITIALIZED);
824                                break;
825                            }
826                            break;
827                        }
828
829                        default:
830                        {
831                            sendErrorResponse = false;
832
833                            setStickyError(err);
834                            postActivityNotificationIfPossible();
835
836                            // actionCode in an uninitialized state is always fatal.
837                            if (mState == UNINITIALIZED) {
838                                actionCode = ACTION_CODE_FATAL;
839                            }
840                            if (mFlags & kFlagIsAsync) {
841                                onError(err, actionCode);
842                            }
843                            switch (actionCode) {
844                            case ACTION_CODE_TRANSIENT:
845                                break;
846                            case ACTION_CODE_RECOVERABLE:
847                                setState(INITIALIZED);
848                                break;
849                            default:
850                                setState(UNINITIALIZED);
851                                break;
852                            }
853                            break;
854                        }
855                    }
856
857                    if (sendErrorResponse) {
858                        PostReplyWithError(mReplyID, err);
859                    }
860                    break;
861                }
862
863                case CodecBase::kWhatComponentAllocated:
864                {
865                    CHECK_EQ(mState, INITIALIZING);
866                    setState(INITIALIZED);
867                    mFlags |= kFlagIsComponentAllocated;
868
869                    CHECK(msg->findString("componentName", &mComponentName));
870
871                    if (mComponentName.startsWith("OMX.google.")) {
872                        mFlags |= kFlagUsesSoftwareRenderer;
873                    } else {
874                        mFlags &= ~kFlagUsesSoftwareRenderer;
875                    }
876
877                    if (mComponentName.endsWith(".secure")) {
878                        mFlags |= kFlagIsSecure;
879                    } else {
880                        mFlags &= ~kFlagIsSecure;
881                    }
882
883                    (new AMessage)->postReply(mReplyID);
884                    break;
885                }
886
887                case CodecBase::kWhatComponentConfigured:
888                {
889                    CHECK_EQ(mState, CONFIGURING);
890
891                    // reset input surface flag
892                    mHaveInputSurface = false;
893
894                    CHECK(msg->findMessage("input-format", &mInputFormat));
895                    CHECK(msg->findMessage("output-format", &mOutputFormat));
896
897                    int32_t usingSwRenderer;
898                    if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
899                            && usingSwRenderer) {
900                        mFlags |= kFlagUsesSoftwareRenderer;
901                    }
902                    setState(CONFIGURED);
903                    (new AMessage)->postReply(mReplyID);
904                    break;
905                }
906
907                case CodecBase::kWhatInputSurfaceCreated:
908                {
909                    // response to initiateCreateInputSurface()
910                    status_t err = NO_ERROR;
911                    sp<AMessage> response = new AMessage();
912                    if (!msg->findInt32("err", &err)) {
913                        sp<RefBase> obj;
914                        msg->findObject("input-surface", &obj);
915                        CHECK(obj != NULL);
916                        response->setObject("input-surface", obj);
917                        mHaveInputSurface = true;
918                    } else {
919                        response->setInt32("err", err);
920                    }
921                    response->postReply(mReplyID);
922                    break;
923                }
924
925                case CodecBase::kWhatSignaledInputEOS:
926                {
927                    // response to signalEndOfInputStream()
928                    sp<AMessage> response = new AMessage();
929                    status_t err;
930                    if (msg->findInt32("err", &err)) {
931                        response->setInt32("err", err);
932                    }
933                    response->postReply(mReplyID);
934                    break;
935                }
936
937
938                case CodecBase::kWhatBuffersAllocated:
939                {
940                    Mutex::Autolock al(mBufferLock);
941                    int32_t portIndex;
942                    CHECK(msg->findInt32("portIndex", &portIndex));
943
944                    ALOGV("%s buffers allocated",
945                          portIndex == kPortIndexInput ? "input" : "output");
946
947                    CHECK(portIndex == kPortIndexInput
948                            || portIndex == kPortIndexOutput);
949
950                    mPortBuffers[portIndex].clear();
951
952                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
953
954                    sp<RefBase> obj;
955                    CHECK(msg->findObject("portDesc", &obj));
956
957                    sp<CodecBase::PortDescription> portDesc =
958                        static_cast<CodecBase::PortDescription *>(obj.get());
959
960                    size_t numBuffers = portDesc->countBuffers();
961
962                    for (size_t i = 0; i < numBuffers; ++i) {
963                        BufferInfo info;
964                        info.mBufferID = portDesc->bufferIDAt(i);
965                        info.mOwnedByClient = false;
966                        info.mData = portDesc->bufferAt(i);
967
968                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
969                            info.mEncryptedData =
970                                new ABuffer(info.mData->capacity());
971                        }
972
973                        buffers->push_back(info);
974                    }
975
976                    if (portIndex == kPortIndexOutput) {
977                        if (mState == STARTING) {
978                            // We're always allocating output buffers after
979                            // allocating input buffers, so this is a good
980                            // indication that now all buffers are allocated.
981                            setState(STARTED);
982                            (new AMessage)->postReply(mReplyID);
983                        } else {
984                            mFlags |= kFlagOutputBuffersChanged;
985                            postActivityNotificationIfPossible();
986                        }
987                    }
988                    break;
989                }
990
991                case CodecBase::kWhatOutputFormatChanged:
992                {
993                    ALOGV("codec output format changed");
994
995                    if (mSoftRenderer == NULL &&
996                            mNativeWindow != NULL &&
997                            (mFlags & kFlagUsesSoftwareRenderer)) {
998                        AString mime;
999                        CHECK(msg->findString("mime", &mime));
1000
1001                        if (mime.startsWithIgnoreCase("video/")) {
1002                            mSoftRenderer = new SoftwareRenderer(mNativeWindow);
1003                        }
1004                    }
1005
1006                    mOutputFormat = msg;
1007
1008                    if (mFlags & kFlagIsEncoder) {
1009                        // Before we announce the format change we should
1010                        // collect codec specific data and amend the output
1011                        // format as necessary.
1012                        mFlags |= kFlagGatherCodecSpecificData;
1013                    } else if (mFlags & kFlagIsAsync) {
1014                        onOutputFormatChanged();
1015                    } else {
1016                        mFlags |= kFlagOutputFormatChanged;
1017                        postActivityNotificationIfPossible();
1018                    }
1019
1020                    // Notify mCrypto of video resolution changes
1021                    if (mCrypto != NULL) {
1022                        int32_t left, top, right, bottom, width, height;
1023                        if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1024                            mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1025                        } else if (mOutputFormat->findInt32("width", &width)
1026                                && mOutputFormat->findInt32("height", &height)) {
1027                            mCrypto->notifyResolution(width, height);
1028                        }
1029                    }
1030
1031                    break;
1032                }
1033
1034                case CodecBase::kWhatFillThisBuffer:
1035                {
1036                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1037
1038                    if (mState == FLUSHING
1039                            || mState == STOPPING
1040                            || mState == RELEASING) {
1041                        returnBuffersToCodecOnPort(kPortIndexInput);
1042                        break;
1043                    }
1044
1045                    if (!mCSD.empty()) {
1046                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1047                        CHECK_GE(index, 0);
1048
1049                        // If codec specific data had been specified as
1050                        // part of the format in the call to configure and
1051                        // if there's more csd left, we submit it here
1052                        // clients only get access to input buffers once
1053                        // this data has been exhausted.
1054
1055                        status_t err = queueCSDInputBuffer(index);
1056
1057                        if (err != OK) {
1058                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1059                                  err);
1060
1061                            setStickyError(err);
1062                            postActivityNotificationIfPossible();
1063
1064                            cancelPendingDequeueOperations();
1065                        }
1066                        break;
1067                    }
1068
1069                    if (mFlags & kFlagIsAsync) {
1070                        if (!mHaveInputSurface) {
1071                            onInputBufferAvailable();
1072                        }
1073                    } else if (mFlags & kFlagDequeueInputPending) {
1074                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1075
1076                        ++mDequeueInputTimeoutGeneration;
1077                        mFlags &= ~kFlagDequeueInputPending;
1078                        mDequeueInputReplyID = 0;
1079                    } else {
1080                        postActivityNotificationIfPossible();
1081                    }
1082                    break;
1083                }
1084
1085                case CodecBase::kWhatDrainThisBuffer:
1086                {
1087                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1088
1089                    if (mState == FLUSHING
1090                            || mState == STOPPING
1091                            || mState == RELEASING) {
1092                        returnBuffersToCodecOnPort(kPortIndexOutput);
1093                        break;
1094                    }
1095
1096                    sp<ABuffer> buffer;
1097                    CHECK(msg->findBuffer("buffer", &buffer));
1098
1099                    int32_t omxFlags;
1100                    CHECK(msg->findInt32("flags", &omxFlags));
1101
1102                    buffer->meta()->setInt32("omxFlags", omxFlags);
1103
1104                    if (mFlags & kFlagGatherCodecSpecificData) {
1105                        // This is the very first output buffer after a
1106                        // format change was signalled, it'll either contain
1107                        // the one piece of codec specific data we can expect
1108                        // or there won't be codec specific data.
1109                        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1110                            status_t err =
1111                                amendOutputFormatWithCodecSpecificData(buffer);
1112
1113                            if (err != OK) {
1114                                ALOGE("Codec spit out malformed codec "
1115                                      "specific data!");
1116                            }
1117                        }
1118
1119                        mFlags &= ~kFlagGatherCodecSpecificData;
1120                        if (mFlags & kFlagIsAsync) {
1121                            onOutputFormatChanged();
1122                        } else {
1123                            mFlags |= kFlagOutputFormatChanged;
1124                        }
1125                    }
1126
1127                    if (mFlags & kFlagIsAsync) {
1128                        onOutputBufferAvailable();
1129                    } else if (mFlags & kFlagDequeueOutputPending) {
1130                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1131
1132                        ++mDequeueOutputTimeoutGeneration;
1133                        mFlags &= ~kFlagDequeueOutputPending;
1134                        mDequeueOutputReplyID = 0;
1135                    } else {
1136                        postActivityNotificationIfPossible();
1137                    }
1138
1139                    break;
1140                }
1141
1142                case CodecBase::kWhatEOS:
1143                {
1144                    // We already notify the client of this by using the
1145                    // corresponding flag in "onOutputBufferReady".
1146                    break;
1147                }
1148
1149                case CodecBase::kWhatShutdownCompleted:
1150                {
1151                    if (mState == STOPPING) {
1152                        setState(INITIALIZED);
1153                    } else {
1154                        CHECK_EQ(mState, RELEASING);
1155                        setState(UNINITIALIZED);
1156                        mComponentName.clear();
1157                    }
1158                    mFlags &= ~kFlagIsComponentAllocated;
1159
1160                    (new AMessage)->postReply(mReplyID);
1161                    break;
1162                }
1163
1164                case CodecBase::kWhatFlushCompleted:
1165                {
1166                    if (mState != FLUSHING) {
1167                        ALOGW("received FlushCompleted message in state %d",
1168                                mState);
1169                        break;
1170                    }
1171
1172                    if (mFlags & kFlagIsAsync) {
1173                        setState(FLUSHED);
1174                    } else {
1175                        setState(STARTED);
1176                        mCodec->signalResume();
1177                    }
1178
1179                    (new AMessage)->postReply(mReplyID);
1180                    break;
1181                }
1182
1183                default:
1184                    TRESPASS();
1185            }
1186            break;
1187        }
1188
1189        case kWhatInit:
1190        {
1191            uint32_t replyID;
1192            CHECK(msg->senderAwaitsResponse(&replyID));
1193
1194            if (mState != UNINITIALIZED) {
1195                PostReplyWithError(replyID, INVALID_OPERATION);
1196                break;
1197            }
1198
1199            mReplyID = replyID;
1200            setState(INITIALIZING);
1201
1202            AString name;
1203            CHECK(msg->findString("name", &name));
1204
1205            int32_t nameIsType;
1206            int32_t encoder = false;
1207            CHECK(msg->findInt32("nameIsType", &nameIsType));
1208            if (nameIsType) {
1209                CHECK(msg->findInt32("encoder", &encoder));
1210            }
1211
1212            sp<AMessage> format = new AMessage;
1213
1214            if (nameIsType) {
1215                format->setString("mime", name.c_str());
1216                format->setInt32("encoder", encoder);
1217            } else {
1218                format->setString("componentName", name.c_str());
1219            }
1220
1221            mCodec->initiateAllocateComponent(format);
1222            break;
1223        }
1224
1225        case kWhatSetCallback:
1226        {
1227            uint32_t replyID;
1228            CHECK(msg->senderAwaitsResponse(&replyID));
1229
1230            if (mState == UNINITIALIZED
1231                    || mState == INITIALIZING
1232                    || isExecuting()) {
1233                // callback can't be set after codec is executing,
1234                // or before it's initialized (as the callback
1235                // will be cleared when it goes to INITIALIZED)
1236                PostReplyWithError(replyID, INVALID_OPERATION);
1237                break;
1238            }
1239
1240            sp<AMessage> callback;
1241            CHECK(msg->findMessage("callback", &callback));
1242
1243            mCallback = callback;
1244
1245            if (mCallback != NULL) {
1246                ALOGI("MediaCodec will operate in async mode");
1247                mFlags |= kFlagIsAsync;
1248            } else {
1249                mFlags &= ~kFlagIsAsync;
1250            }
1251
1252            sp<AMessage> response = new AMessage;
1253            response->postReply(replyID);
1254            break;
1255        }
1256
1257        case kWhatConfigure:
1258        {
1259            uint32_t replyID;
1260            CHECK(msg->senderAwaitsResponse(&replyID));
1261
1262            if (mState != INITIALIZED) {
1263                PostReplyWithError(replyID, INVALID_OPERATION);
1264                break;
1265            }
1266
1267            sp<RefBase> obj;
1268            if (!msg->findObject("native-window", &obj)) {
1269                obj.clear();
1270            }
1271
1272            sp<AMessage> format;
1273            CHECK(msg->findMessage("format", &format));
1274
1275            if (obj != NULL) {
1276                format->setObject("native-window", obj);
1277
1278                status_t err = setNativeWindow(
1279                    static_cast<NativeWindowWrapper *>(obj.get())
1280                        ->getSurfaceTextureClient());
1281
1282                if (err != OK) {
1283                    PostReplyWithError(replyID, err);
1284                    break;
1285                }
1286            } else {
1287                setNativeWindow(NULL);
1288            }
1289
1290            mReplyID = replyID;
1291            setState(CONFIGURING);
1292
1293            void *crypto;
1294            if (!msg->findPointer("crypto", &crypto)) {
1295                crypto = NULL;
1296            }
1297
1298            mCrypto = static_cast<ICrypto *>(crypto);
1299
1300            uint32_t flags;
1301            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1302
1303            if (flags & CONFIGURE_FLAG_ENCODE) {
1304                format->setInt32("encoder", true);
1305                mFlags |= kFlagIsEncoder;
1306            }
1307
1308            extractCSD(format);
1309
1310            mCodec->initiateConfigureComponent(format);
1311            break;
1312        }
1313
1314        case kWhatCreateInputSurface:
1315        {
1316            uint32_t replyID;
1317            CHECK(msg->senderAwaitsResponse(&replyID));
1318
1319            // Must be configured, but can't have been started yet.
1320            if (mState != CONFIGURED) {
1321                PostReplyWithError(replyID, INVALID_OPERATION);
1322                break;
1323            }
1324
1325            mReplyID = replyID;
1326            mCodec->initiateCreateInputSurface();
1327            break;
1328        }
1329
1330        case kWhatStart:
1331        {
1332            uint32_t replyID;
1333            CHECK(msg->senderAwaitsResponse(&replyID));
1334
1335            if (mState == FLUSHED) {
1336                setState(STARTED);
1337                mCodec->signalResume();
1338                PostReplyWithError(replyID, OK);
1339                break;
1340            } else if (mState != CONFIGURED) {
1341                PostReplyWithError(replyID, INVALID_OPERATION);
1342                break;
1343            }
1344
1345            mReplyID = replyID;
1346            setState(STARTING);
1347
1348            mCodec->initiateStart();
1349            break;
1350        }
1351
1352        case kWhatStop:
1353        case kWhatRelease:
1354        {
1355            State targetState =
1356                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1357
1358            uint32_t replyID;
1359            CHECK(msg->senderAwaitsResponse(&replyID));
1360
1361            if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
1362                    && mState != INITIALIZED
1363                    && mState != CONFIGURED && !isExecuting()) {
1364                // 1) Permit release to shut down the component if allocated.
1365                //
1366                // 2) We may be in "UNINITIALIZED" state already and
1367                // also shutdown the encoder/decoder without the
1368                // client being aware of this if media server died while
1369                // we were being stopped. The client would assume that
1370                // after stop() returned, it would be safe to call release()
1371                // and it should be in this case, no harm to allow a release()
1372                // if we're already uninitialized.
1373                sp<AMessage> response = new AMessage;
1374                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1375                response->setInt32("err", err);
1376                if (err == OK && targetState == UNINITIALIZED) {
1377                    mComponentName.clear();
1378                }
1379                response->postReply(replyID);
1380                break;
1381            }
1382
1383            if (mFlags & kFlagSawMediaServerDie) {
1384                // It's dead, Jim. Don't expect initiateShutdown to yield
1385                // any useful results now...
1386                setState(UNINITIALIZED);
1387                if (targetState == UNINITIALIZED) {
1388                    mComponentName.clear();
1389                }
1390                (new AMessage)->postReply(replyID);
1391                break;
1392            }
1393
1394            mReplyID = replyID;
1395            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1396
1397            mCodec->initiateShutdown(
1398                    msg->what() == kWhatStop /* keepComponentAllocated */);
1399
1400            returnBuffersToCodec();
1401            break;
1402        }
1403
1404        case kWhatDequeueInputBuffer:
1405        {
1406            uint32_t replyID;
1407            CHECK(msg->senderAwaitsResponse(&replyID));
1408
1409            if (mFlags & kFlagIsAsync) {
1410                ALOGE("dequeueOutputBuffer can't be used in async mode");
1411                PostReplyWithError(replyID, INVALID_OPERATION);
1412                break;
1413            }
1414
1415            if (mHaveInputSurface) {
1416                ALOGE("dequeueInputBuffer can't be used with input surface");
1417                PostReplyWithError(replyID, INVALID_OPERATION);
1418                break;
1419            }
1420
1421            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1422                break;
1423            }
1424
1425            int64_t timeoutUs;
1426            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1427
1428            if (timeoutUs == 0ll) {
1429                PostReplyWithError(replyID, -EAGAIN);
1430                break;
1431            }
1432
1433            mFlags |= kFlagDequeueInputPending;
1434            mDequeueInputReplyID = replyID;
1435
1436            if (timeoutUs > 0ll) {
1437                sp<AMessage> timeoutMsg =
1438                    new AMessage(kWhatDequeueInputTimedOut, id());
1439                timeoutMsg->setInt32(
1440                        "generation", ++mDequeueInputTimeoutGeneration);
1441                timeoutMsg->post(timeoutUs);
1442            }
1443            break;
1444        }
1445
1446        case kWhatDequeueInputTimedOut:
1447        {
1448            int32_t generation;
1449            CHECK(msg->findInt32("generation", &generation));
1450
1451            if (generation != mDequeueInputTimeoutGeneration) {
1452                // Obsolete
1453                break;
1454            }
1455
1456            CHECK(mFlags & kFlagDequeueInputPending);
1457
1458            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
1459
1460            mFlags &= ~kFlagDequeueInputPending;
1461            mDequeueInputReplyID = 0;
1462            break;
1463        }
1464
1465        case kWhatQueueInputBuffer:
1466        {
1467            uint32_t replyID;
1468            CHECK(msg->senderAwaitsResponse(&replyID));
1469
1470            if (!isExecuting()) {
1471                PostReplyWithError(replyID, INVALID_OPERATION);
1472                break;
1473            } else if (mFlags & kFlagStickyError) {
1474                PostReplyWithError(replyID, getStickyError());
1475                break;
1476            }
1477
1478            status_t err = onQueueInputBuffer(msg);
1479
1480            PostReplyWithError(replyID, err);
1481            break;
1482        }
1483
1484        case kWhatDequeueOutputBuffer:
1485        {
1486            uint32_t replyID;
1487            CHECK(msg->senderAwaitsResponse(&replyID));
1488
1489            if (mFlags & kFlagIsAsync) {
1490                ALOGE("dequeueOutputBuffer can't be used in async mode");
1491                PostReplyWithError(replyID, INVALID_OPERATION);
1492                break;
1493            }
1494
1495            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1496                break;
1497            }
1498
1499            int64_t timeoutUs;
1500            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1501
1502            if (timeoutUs == 0ll) {
1503                PostReplyWithError(replyID, -EAGAIN);
1504                break;
1505            }
1506
1507            mFlags |= kFlagDequeueOutputPending;
1508            mDequeueOutputReplyID = replyID;
1509
1510            if (timeoutUs > 0ll) {
1511                sp<AMessage> timeoutMsg =
1512                    new AMessage(kWhatDequeueOutputTimedOut, id());
1513                timeoutMsg->setInt32(
1514                        "generation", ++mDequeueOutputTimeoutGeneration);
1515                timeoutMsg->post(timeoutUs);
1516            }
1517            break;
1518        }
1519
1520        case kWhatDequeueOutputTimedOut:
1521        {
1522            int32_t generation;
1523            CHECK(msg->findInt32("generation", &generation));
1524
1525            if (generation != mDequeueOutputTimeoutGeneration) {
1526                // Obsolete
1527                break;
1528            }
1529
1530            CHECK(mFlags & kFlagDequeueOutputPending);
1531
1532            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
1533
1534            mFlags &= ~kFlagDequeueOutputPending;
1535            mDequeueOutputReplyID = 0;
1536            break;
1537        }
1538
1539        case kWhatReleaseOutputBuffer:
1540        {
1541            uint32_t replyID;
1542            CHECK(msg->senderAwaitsResponse(&replyID));
1543
1544            if (!isExecuting()) {
1545                PostReplyWithError(replyID, INVALID_OPERATION);
1546                break;
1547            } else if (mFlags & kFlagStickyError) {
1548                PostReplyWithError(replyID, getStickyError());
1549                break;
1550            }
1551
1552            status_t err = onReleaseOutputBuffer(msg);
1553
1554            PostReplyWithError(replyID, err);
1555            break;
1556        }
1557
1558        case kWhatSignalEndOfInputStream:
1559        {
1560            uint32_t replyID;
1561            CHECK(msg->senderAwaitsResponse(&replyID));
1562
1563            if (!isExecuting()) {
1564                PostReplyWithError(replyID, INVALID_OPERATION);
1565                break;
1566            } else if (mFlags & kFlagStickyError) {
1567                PostReplyWithError(replyID, getStickyError());
1568                break;
1569            }
1570
1571            mReplyID = replyID;
1572            mCodec->signalEndOfInputStream();
1573            break;
1574        }
1575
1576        case kWhatGetBuffers:
1577        {
1578            uint32_t replyID;
1579            CHECK(msg->senderAwaitsResponse(&replyID));
1580
1581            if (!isExecuting() || (mFlags & kFlagIsAsync)) {
1582                PostReplyWithError(replyID, INVALID_OPERATION);
1583                break;
1584            } else if (mFlags & kFlagStickyError) {
1585                PostReplyWithError(replyID, getStickyError());
1586                break;
1587            }
1588
1589            int32_t portIndex;
1590            CHECK(msg->findInt32("portIndex", &portIndex));
1591
1592            Vector<sp<ABuffer> > *dstBuffers;
1593            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1594
1595            dstBuffers->clear();
1596            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1597
1598            for (size_t i = 0; i < srcBuffers.size(); ++i) {
1599                const BufferInfo &info = srcBuffers.itemAt(i);
1600
1601                dstBuffers->push_back(
1602                        (portIndex == kPortIndexInput && mCrypto != NULL)
1603                                ? info.mEncryptedData : info.mData);
1604            }
1605
1606            (new AMessage)->postReply(replyID);
1607            break;
1608        }
1609
1610        case kWhatFlush:
1611        {
1612            uint32_t replyID;
1613            CHECK(msg->senderAwaitsResponse(&replyID));
1614
1615            if (!isExecuting()) {
1616                PostReplyWithError(replyID, INVALID_OPERATION);
1617                break;
1618            } else if (mFlags & kFlagStickyError) {
1619                PostReplyWithError(replyID, getStickyError());
1620                break;
1621            }
1622
1623            mReplyID = replyID;
1624            // TODO: skip flushing if already FLUSHED
1625            setState(FLUSHING);
1626
1627            mCodec->signalFlush();
1628            returnBuffersToCodec();
1629            break;
1630        }
1631
1632        case kWhatGetInputFormat:
1633        case kWhatGetOutputFormat:
1634        {
1635            sp<AMessage> format =
1636                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
1637
1638            uint32_t replyID;
1639            CHECK(msg->senderAwaitsResponse(&replyID));
1640
1641            if ((mState != CONFIGURED && mState != STARTING &&
1642                 mState != STARTED && mState != FLUSHING &&
1643                 mState != FLUSHED)
1644                    || format == NULL) {
1645                PostReplyWithError(replyID, INVALID_OPERATION);
1646                break;
1647            } else if (mFlags & kFlagStickyError) {
1648                PostReplyWithError(replyID, getStickyError());
1649                break;
1650            }
1651
1652            sp<AMessage> response = new AMessage;
1653            response->setMessage("format", format);
1654            response->postReply(replyID);
1655            break;
1656        }
1657
1658        case kWhatRequestIDRFrame:
1659        {
1660            mCodec->signalRequestIDRFrame();
1661            break;
1662        }
1663
1664        case kWhatRequestActivityNotification:
1665        {
1666            CHECK(mActivityNotify == NULL);
1667            CHECK(msg->findMessage("notify", &mActivityNotify));
1668
1669            postActivityNotificationIfPossible();
1670            break;
1671        }
1672
1673        case kWhatGetName:
1674        {
1675            uint32_t replyID;
1676            CHECK(msg->senderAwaitsResponse(&replyID));
1677
1678            if (mComponentName.empty()) {
1679                PostReplyWithError(replyID, INVALID_OPERATION);
1680                break;
1681            }
1682
1683            sp<AMessage> response = new AMessage;
1684            response->setString("name", mComponentName.c_str());
1685            response->postReply(replyID);
1686            break;
1687        }
1688
1689        case kWhatSetParameters:
1690        {
1691            uint32_t replyID;
1692            CHECK(msg->senderAwaitsResponse(&replyID));
1693
1694            sp<AMessage> params;
1695            CHECK(msg->findMessage("params", &params));
1696
1697            status_t err = onSetParameters(params);
1698
1699            PostReplyWithError(replyID, err);
1700            break;
1701        }
1702
1703        default:
1704            TRESPASS();
1705    }
1706}
1707
1708void MediaCodec::extractCSD(const sp<AMessage> &format) {
1709    mCSD.clear();
1710
1711    size_t i = 0;
1712    for (;;) {
1713        sp<ABuffer> csd;
1714        if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
1715            break;
1716        }
1717
1718        mCSD.push_back(csd);
1719        ++i;
1720    }
1721
1722    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
1723}
1724
1725status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1726    CHECK(!mCSD.empty());
1727
1728    const BufferInfo *info =
1729        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
1730
1731    sp<ABuffer> csd = *mCSD.begin();
1732    mCSD.erase(mCSD.begin());
1733
1734    const sp<ABuffer> &codecInputData =
1735        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1736
1737    if (csd->size() > codecInputData->capacity()) {
1738        return -EINVAL;
1739    }
1740
1741    memcpy(codecInputData->data(), csd->data(), csd->size());
1742
1743    AString errorDetailMsg;
1744
1745    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1746    msg->setSize("index", bufferIndex);
1747    msg->setSize("offset", 0);
1748    msg->setSize("size", csd->size());
1749    msg->setInt64("timeUs", 0ll);
1750    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1751    msg->setPointer("errorDetailMsg", &errorDetailMsg);
1752
1753    return onQueueInputBuffer(msg);
1754}
1755
1756void MediaCodec::setState(State newState) {
1757    if (newState == INITIALIZED || newState == UNINITIALIZED) {
1758        delete mSoftRenderer;
1759        mSoftRenderer = NULL;
1760
1761        mCrypto.clear();
1762        setNativeWindow(NULL);
1763
1764        mInputFormat.clear();
1765        mOutputFormat.clear();
1766        mFlags &= ~kFlagOutputFormatChanged;
1767        mFlags &= ~kFlagOutputBuffersChanged;
1768        mFlags &= ~kFlagStickyError;
1769        mFlags &= ~kFlagIsEncoder;
1770        mFlags &= ~kFlagGatherCodecSpecificData;
1771        mFlags &= ~kFlagIsAsync;
1772        mStickyError = OK;
1773
1774        mActivityNotify.clear();
1775        mCallback.clear();
1776    }
1777
1778    if (newState == UNINITIALIZED) {
1779        // return any straggling buffers, e.g. if we got here on an error
1780        returnBuffersToCodec();
1781
1782        // The component is gone, mediaserver's probably back up already
1783        // but should definitely be back up should we try to instantiate
1784        // another component.. and the cycle continues.
1785        mFlags &= ~kFlagSawMediaServerDie;
1786    }
1787
1788    mState = newState;
1789
1790    cancelPendingDequeueOperations();
1791
1792    updateBatteryStat();
1793}
1794
1795void MediaCodec::returnBuffersToCodec() {
1796    returnBuffersToCodecOnPort(kPortIndexInput);
1797    returnBuffersToCodecOnPort(kPortIndexOutput);
1798}
1799
1800void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1801    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1802    Mutex::Autolock al(mBufferLock);
1803
1804    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1805
1806    for (size_t i = 0; i < buffers->size(); ++i) {
1807        BufferInfo *info = &buffers->editItemAt(i);
1808
1809        if (info->mNotify != NULL) {
1810            sp<AMessage> msg = info->mNotify;
1811            info->mNotify = NULL;
1812            info->mOwnedByClient = false;
1813
1814            if (portIndex == kPortIndexInput) {
1815                /* no error, just returning buffers */
1816                msg->setInt32("err", OK);
1817            }
1818            msg->post();
1819        }
1820    }
1821
1822    mAvailPortBuffers[portIndex].clear();
1823}
1824
1825size_t MediaCodec::updateBuffers(
1826        int32_t portIndex, const sp<AMessage> &msg) {
1827    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1828
1829    uint32_t bufferID;
1830    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
1831
1832    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1833
1834    for (size_t i = 0; i < buffers->size(); ++i) {
1835        BufferInfo *info = &buffers->editItemAt(i);
1836
1837        if (info->mBufferID == bufferID) {
1838            CHECK(info->mNotify == NULL);
1839            CHECK(msg->findMessage("reply", &info->mNotify));
1840
1841            info->mFormat =
1842                (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
1843            mAvailPortBuffers[portIndex].push_back(i);
1844
1845            return i;
1846        }
1847    }
1848
1849    TRESPASS();
1850
1851    return 0;
1852}
1853
1854status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1855    size_t index;
1856    size_t offset;
1857    size_t size;
1858    int64_t timeUs;
1859    uint32_t flags;
1860    CHECK(msg->findSize("index", &index));
1861    CHECK(msg->findSize("offset", &offset));
1862    CHECK(msg->findInt64("timeUs", &timeUs));
1863    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1864
1865    const CryptoPlugin::SubSample *subSamples;
1866    size_t numSubSamples;
1867    const uint8_t *key;
1868    const uint8_t *iv;
1869    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1870
1871    // We allow the simpler queueInputBuffer API to be used even in
1872    // secure mode, by fabricating a single unencrypted subSample.
1873    CryptoPlugin::SubSample ss;
1874
1875    if (msg->findSize("size", &size)) {
1876        if (mCrypto != NULL) {
1877            ss.mNumBytesOfClearData = size;
1878            ss.mNumBytesOfEncryptedData = 0;
1879
1880            subSamples = &ss;
1881            numSubSamples = 1;
1882            key = NULL;
1883            iv = NULL;
1884        }
1885    } else {
1886        if (mCrypto == NULL) {
1887            return -EINVAL;
1888        }
1889
1890        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1891        CHECK(msg->findSize("numSubSamples", &numSubSamples));
1892        CHECK(msg->findPointer("key", (void **)&key));
1893        CHECK(msg->findPointer("iv", (void **)&iv));
1894
1895        int32_t tmp;
1896        CHECK(msg->findInt32("mode", &tmp));
1897
1898        mode = (CryptoPlugin::Mode)tmp;
1899
1900        size = 0;
1901        for (size_t i = 0; i < numSubSamples; ++i) {
1902            size += subSamples[i].mNumBytesOfClearData;
1903            size += subSamples[i].mNumBytesOfEncryptedData;
1904        }
1905    }
1906
1907    if (index >= mPortBuffers[kPortIndexInput].size()) {
1908        return -ERANGE;
1909    }
1910
1911    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1912
1913    if (info->mNotify == NULL || !info->mOwnedByClient) {
1914        return -EACCES;
1915    }
1916
1917    if (offset + size > info->mData->capacity()) {
1918        return -EINVAL;
1919    }
1920
1921    sp<AMessage> reply = info->mNotify;
1922    info->mData->setRange(offset, size);
1923    info->mData->meta()->setInt64("timeUs", timeUs);
1924
1925    if (flags & BUFFER_FLAG_EOS) {
1926        info->mData->meta()->setInt32("eos", true);
1927    }
1928
1929    if (flags & BUFFER_FLAG_CODECCONFIG) {
1930        info->mData->meta()->setInt32("csd", true);
1931    }
1932
1933    if (mCrypto != NULL) {
1934        if (size > info->mEncryptedData->capacity()) {
1935            return -ERANGE;
1936        }
1937
1938        AString *errorDetailMsg;
1939        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1940
1941        ssize_t result = mCrypto->decrypt(
1942                (mFlags & kFlagIsSecure) != 0,
1943                key,
1944                iv,
1945                mode,
1946                info->mEncryptedData->base() + offset,
1947                subSamples,
1948                numSubSamples,
1949                info->mData->base(),
1950                errorDetailMsg);
1951
1952        if (result < 0) {
1953            return result;
1954        }
1955
1956        info->mData->setRange(0, result);
1957    }
1958
1959    // synchronization boundary for getBufferAndFormat
1960    {
1961        Mutex::Autolock al(mBufferLock);
1962        info->mOwnedByClient = false;
1963    }
1964    reply->setBuffer("buffer", info->mData);
1965    reply->post();
1966
1967    info->mNotify = NULL;
1968
1969    return OK;
1970}
1971
1972status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1973    size_t index;
1974    CHECK(msg->findSize("index", &index));
1975
1976    int32_t render;
1977    if (!msg->findInt32("render", &render)) {
1978        render = 0;
1979    }
1980
1981    if (!isExecuting()) {
1982        return -EINVAL;
1983    }
1984
1985    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1986        return -ERANGE;
1987    }
1988
1989    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1990
1991    if (info->mNotify == NULL || !info->mOwnedByClient) {
1992        return -EACCES;
1993    }
1994
1995    // synchronization boundary for getBufferAndFormat
1996    {
1997        Mutex::Autolock al(mBufferLock);
1998        info->mOwnedByClient = false;
1999    }
2000
2001    if (render && info->mData != NULL && info->mData->size() != 0) {
2002        info->mNotify->setInt32("render", true);
2003
2004        int64_t timestampNs = 0;
2005        if (msg->findInt64("timestampNs", &timestampNs)) {
2006            info->mNotify->setInt64("timestampNs", timestampNs);
2007        } else {
2008            // TODO: it seems like we should use the timestamp
2009            // in the (media)buffer as it potentially came from
2010            // an input surface, but we did not propagate it prior to
2011            // API 20.  Perhaps check for target SDK version.
2012#if 0
2013            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
2014                ALOGV("using buffer PTS of %" PRId64, timestampNs);
2015                timestampNs *= 1000;
2016            }
2017#endif
2018        }
2019
2020        if (mSoftRenderer != NULL) {
2021            mSoftRenderer->render(
2022                    info->mData->data(), info->mData->size(),
2023                    timestampNs, NULL, info->mFormat);
2024        }
2025    }
2026
2027    info->mNotify->post();
2028    info->mNotify = NULL;
2029
2030    return OK;
2031}
2032
2033ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2034    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2035
2036    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2037
2038    if (availBuffers->empty()) {
2039        return -EAGAIN;
2040    }
2041
2042    size_t index = *availBuffers->begin();
2043    availBuffers->erase(availBuffers->begin());
2044
2045    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2046    CHECK(!info->mOwnedByClient);
2047    {
2048        Mutex::Autolock al(mBufferLock);
2049        info->mOwnedByClient = true;
2050
2051        // set image-data
2052        if (info->mFormat != NULL) {
2053            sp<ABuffer> imageData;
2054            if (info->mFormat->findBuffer("image-data", &imageData)) {
2055                info->mData->meta()->setBuffer("image-data", imageData);
2056            }
2057            int32_t left, top, right, bottom;
2058            if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2059                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2060            }
2061        }
2062    }
2063
2064    return index;
2065}
2066
2067status_t MediaCodec::setNativeWindow(
2068        const sp<Surface> &surfaceTextureClient) {
2069    status_t err;
2070
2071    if (mNativeWindow != NULL) {
2072        err = native_window_api_disconnect(
2073                mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
2074
2075        if (err != OK) {
2076            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
2077                    strerror(-err), err);
2078        }
2079
2080        mNativeWindow.clear();
2081    }
2082
2083    if (surfaceTextureClient != NULL) {
2084        err = native_window_api_connect(
2085                surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
2086
2087        if (err != OK) {
2088            ALOGE("native_window_api_connect returned an error: %s (%d)",
2089                    strerror(-err), err);
2090
2091            return err;
2092        }
2093
2094        mNativeWindow = surfaceTextureClient;
2095    }
2096
2097    return OK;
2098}
2099
2100void MediaCodec::onInputBufferAvailable() {
2101    int32_t index;
2102    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2103        sp<AMessage> msg = mCallback->dup();
2104        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2105        msg->setInt32("index", index);
2106        msg->post();
2107    }
2108}
2109
2110void MediaCodec::onOutputBufferAvailable() {
2111    int32_t index;
2112    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2113        const sp<ABuffer> &buffer =
2114            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2115        sp<AMessage> msg = mCallback->dup();
2116        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2117        msg->setInt32("index", index);
2118        msg->setSize("offset", buffer->offset());
2119        msg->setSize("size", buffer->size());
2120
2121        int64_t timeUs;
2122        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2123
2124        msg->setInt64("timeUs", timeUs);
2125
2126        int32_t omxFlags;
2127        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2128
2129        uint32_t flags = 0;
2130        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2131            flags |= BUFFER_FLAG_SYNCFRAME;
2132        }
2133        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2134            flags |= BUFFER_FLAG_CODECCONFIG;
2135        }
2136        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2137            flags |= BUFFER_FLAG_EOS;
2138        }
2139
2140        msg->setInt32("flags", flags);
2141
2142        msg->post();
2143    }
2144}
2145
2146void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2147    if (mCallback != NULL) {
2148        sp<AMessage> msg = mCallback->dup();
2149        msg->setInt32("callbackID", CB_ERROR);
2150        msg->setInt32("err", err);
2151        msg->setInt32("actionCode", actionCode);
2152
2153        if (detail != NULL) {
2154            msg->setString("detail", detail);
2155        }
2156
2157        msg->post();
2158    }
2159}
2160
2161void MediaCodec::onOutputFormatChanged() {
2162    if (mCallback != NULL) {
2163        sp<AMessage> msg = mCallback->dup();
2164        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2165        msg->setMessage("format", mOutputFormat);
2166        msg->post();
2167    }
2168}
2169
2170
2171void MediaCodec::postActivityNotificationIfPossible() {
2172    if (mActivityNotify == NULL) {
2173        return;
2174    }
2175
2176    bool isErrorOrOutputChanged =
2177            (mFlags & (kFlagStickyError
2178                    | kFlagOutputBuffersChanged
2179                    | kFlagOutputFormatChanged));
2180
2181    if (isErrorOrOutputChanged
2182            || !mAvailPortBuffers[kPortIndexInput].empty()
2183            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2184        mActivityNotify->setInt32("input-buffers",
2185                mAvailPortBuffers[kPortIndexInput].size());
2186
2187        if (isErrorOrOutputChanged) {
2188            // we want consumer to dequeue as many times as it can
2189            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2190        } else {
2191            mActivityNotify->setInt32("output-buffers",
2192                    mAvailPortBuffers[kPortIndexOutput].size());
2193        }
2194        mActivityNotify->post();
2195        mActivityNotify.clear();
2196    }
2197}
2198
2199status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2200    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
2201    msg->setMessage("params", params);
2202
2203    sp<AMessage> response;
2204    return PostAndAwaitResponse(msg, &response);
2205}
2206
2207status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2208    mCodec->signalSetParameters(params);
2209
2210    return OK;
2211}
2212
2213status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2214        const sp<ABuffer> &buffer) {
2215    AString mime;
2216    CHECK(mOutputFormat->findString("mime", &mime));
2217
2218    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2219        // Codec specific data should be SPS and PPS in a single buffer,
2220        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2221        // We separate the two and put them into the output format
2222        // under the keys "csd-0" and "csd-1".
2223
2224        unsigned csdIndex = 0;
2225
2226        const uint8_t *data = buffer->data();
2227        size_t size = buffer->size();
2228
2229        const uint8_t *nalStart;
2230        size_t nalSize;
2231        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2232            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2233            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2234            memcpy(csd->data() + 4, nalStart, nalSize);
2235
2236            mOutputFormat->setBuffer(
2237                    StringPrintf("csd-%u", csdIndex).c_str(), csd);
2238
2239            ++csdIndex;
2240        }
2241
2242        if (csdIndex != 2) {
2243            return ERROR_MALFORMED;
2244        }
2245    } else {
2246        // For everything else we just stash the codec specific data into
2247        // the output format as a single piece of csd under "csd-0".
2248        mOutputFormat->setBuffer("csd-0", buffer);
2249    }
2250
2251    return OK;
2252}
2253
2254void MediaCodec::updateBatteryStat() {
2255    if (mState == CONFIGURED && !mBatteryStatNotified) {
2256        AString mime;
2257        CHECK(mOutputFormat != NULL &&
2258                mOutputFormat->findString("mime", &mime));
2259
2260        mIsVideo = mime.startsWithIgnoreCase("video/");
2261
2262        BatteryNotifier& notifier(BatteryNotifier::getInstance());
2263
2264        if (mIsVideo) {
2265            notifier.noteStartVideo();
2266        } else {
2267            notifier.noteStartAudio();
2268        }
2269
2270        mBatteryStatNotified = true;
2271    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2272        BatteryNotifier& notifier(BatteryNotifier::getInstance());
2273
2274        if (mIsVideo) {
2275            notifier.noteStopVideo();
2276        } else {
2277            notifier.noteStopAudio();
2278        }
2279
2280        mBatteryStatNotified = false;
2281    }
2282}
2283
2284}  // namespace android
2285