MediaCodec.cpp revision a1e8944a21e5833b7aadc451776f11797f5f9273
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                    }
742
743                    bool sendErrorResponse = true;
744
745                    switch (mState) {
746                        case INITIALIZING:
747                        {
748                            setState(UNINITIALIZED);
749                            break;
750                        }
751
752                        case CONFIGURING:
753                        {
754                            setState(actionCode == ACTION_CODE_FATAL ?
755                                    UNINITIALIZED : INITIALIZED);
756                            break;
757                        }
758
759                        case STARTING:
760                        {
761                            setState(actionCode == ACTION_CODE_FATAL ?
762                                    UNINITIALIZED : CONFIGURED);
763                            break;
764                        }
765
766                        case STOPPING:
767                        case RELEASING:
768                        {
769                            // Ignore the error, assuming we'll still get
770                            // the shutdown complete notification.
771
772                            sendErrorResponse = false;
773
774                            if (mFlags & kFlagSawMediaServerDie) {
775                                // MediaServer died, there definitely won't
776                                // be a shutdown complete notification after
777                                // all.
778
779                                // note that we're directly going from
780                                // STOPPING->UNINITIALIZED, instead of the
781                                // usual STOPPING->INITIALIZED state.
782                                setState(UNINITIALIZED);
783                                if (mState == RELEASING) {
784                                    mComponentName.clear();
785                                }
786                                (new AMessage)->postReply(mReplyID);
787                            }
788                            break;
789                        }
790
791                        case FLUSHING:
792                        {
793                            if (actionCode == ACTION_CODE_FATAL) {
794                                setState(UNINITIALIZED);
795                            } else {
796                                setState(
797                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
798                            }
799                            break;
800                        }
801
802                        case FLUSHED:
803                        case STARTED:
804                        {
805                            sendErrorResponse = false;
806
807                            setStickyError(err);
808                            postActivityNotificationIfPossible();
809
810                            cancelPendingDequeueOperations();
811
812                            if (mFlags & kFlagIsAsync) {
813                                onError(err, actionCode);
814                            }
815                            switch (actionCode) {
816                            case ACTION_CODE_TRANSIENT:
817                                break;
818                            case ACTION_CODE_RECOVERABLE:
819                                setState(INITIALIZED);
820                                break;
821                            default:
822                                setState(UNINITIALIZED);
823                                break;
824                            }
825                            break;
826                        }
827
828                        default:
829                        {
830                            sendErrorResponse = false;
831
832                            setStickyError(err);
833                            postActivityNotificationIfPossible();
834
835                            // actionCode in an uninitialized state is always fatal.
836                            if (mState == UNINITIALIZED) {
837                                actionCode = ACTION_CODE_FATAL;
838                            }
839                            if (mFlags & kFlagIsAsync) {
840                                onError(err, actionCode);
841                            }
842                            switch (actionCode) {
843                            case ACTION_CODE_TRANSIENT:
844                                break;
845                            case ACTION_CODE_RECOVERABLE:
846                                setState(INITIALIZED);
847                                break;
848                            default:
849                                setState(UNINITIALIZED);
850                                break;
851                            }
852                            break;
853                        }
854                    }
855
856                    if (sendErrorResponse) {
857                        PostReplyWithError(mReplyID, err);
858                    }
859                    break;
860                }
861
862                case CodecBase::kWhatComponentAllocated:
863                {
864                    CHECK_EQ(mState, INITIALIZING);
865                    setState(INITIALIZED);
866
867                    CHECK(msg->findString("componentName", &mComponentName));
868
869                    if (mComponentName.startsWith("OMX.google.")) {
870                        mFlags |= kFlagIsSoftwareCodec;
871                    } else {
872                        mFlags &= ~kFlagIsSoftwareCodec;
873                    }
874
875                    if (mComponentName.endsWith(".secure")) {
876                        mFlags |= kFlagIsSecure;
877                    } else {
878                        mFlags &= ~kFlagIsSecure;
879                    }
880
881                    (new AMessage)->postReply(mReplyID);
882                    break;
883                }
884
885                case CodecBase::kWhatComponentConfigured:
886                {
887                    CHECK_EQ(mState, CONFIGURING);
888
889                    // reset input surface flag
890                    mHaveInputSurface = false;
891
892                    CHECK(msg->findMessage("input-format", &mInputFormat));
893                    CHECK(msg->findMessage("output-format", &mOutputFormat));
894
895                    setState(CONFIGURED);
896                    (new AMessage)->postReply(mReplyID);
897                    break;
898                }
899
900                case CodecBase::kWhatInputSurfaceCreated:
901                {
902                    // response to initiateCreateInputSurface()
903                    status_t err = NO_ERROR;
904                    sp<AMessage> response = new AMessage();
905                    if (!msg->findInt32("err", &err)) {
906                        sp<RefBase> obj;
907                        msg->findObject("input-surface", &obj);
908                        CHECK(obj != NULL);
909                        response->setObject("input-surface", obj);
910                        mHaveInputSurface = true;
911                    } else {
912                        response->setInt32("err", err);
913                    }
914                    response->postReply(mReplyID);
915                    break;
916                }
917
918                case CodecBase::kWhatSignaledInputEOS:
919                {
920                    // response to signalEndOfInputStream()
921                    sp<AMessage> response = new AMessage();
922                    status_t err;
923                    if (msg->findInt32("err", &err)) {
924                        response->setInt32("err", err);
925                    }
926                    response->postReply(mReplyID);
927                    break;
928                }
929
930
931                case CodecBase::kWhatBuffersAllocated:
932                {
933                    Mutex::Autolock al(mBufferLock);
934                    int32_t portIndex;
935                    CHECK(msg->findInt32("portIndex", &portIndex));
936
937                    ALOGV("%s buffers allocated",
938                          portIndex == kPortIndexInput ? "input" : "output");
939
940                    CHECK(portIndex == kPortIndexInput
941                            || portIndex == kPortIndexOutput);
942
943                    mPortBuffers[portIndex].clear();
944
945                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
946
947                    sp<RefBase> obj;
948                    CHECK(msg->findObject("portDesc", &obj));
949
950                    sp<CodecBase::PortDescription> portDesc =
951                        static_cast<CodecBase::PortDescription *>(obj.get());
952
953                    size_t numBuffers = portDesc->countBuffers();
954
955                    for (size_t i = 0; i < numBuffers; ++i) {
956                        BufferInfo info;
957                        info.mBufferID = portDesc->bufferIDAt(i);
958                        info.mOwnedByClient = false;
959                        info.mData = portDesc->bufferAt(i);
960
961                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
962                            info.mEncryptedData =
963                                new ABuffer(info.mData->capacity());
964                        }
965
966                        buffers->push_back(info);
967                    }
968
969                    if (portIndex == kPortIndexOutput) {
970                        if (mState == STARTING) {
971                            // We're always allocating output buffers after
972                            // allocating input buffers, so this is a good
973                            // indication that now all buffers are allocated.
974                            setState(STARTED);
975                            (new AMessage)->postReply(mReplyID);
976                        } else {
977                            mFlags |= kFlagOutputBuffersChanged;
978                            postActivityNotificationIfPossible();
979                        }
980                    }
981                    break;
982                }
983
984                case CodecBase::kWhatOutputFormatChanged:
985                {
986                    ALOGV("codec output format changed");
987
988                    if (mSoftRenderer == NULL &&
989                            mNativeWindow != NULL &&
990                            (mFlags & kFlagIsSoftwareCodec)) {
991                        AString mime;
992                        CHECK(msg->findString("mime", &mime));
993
994                        if (mime.startsWithIgnoreCase("video/")) {
995                            mSoftRenderer = new SoftwareRenderer(mNativeWindow);
996                        }
997                    }
998
999                    mOutputFormat = msg;
1000
1001                    if (mFlags & kFlagIsEncoder) {
1002                        // Before we announce the format change we should
1003                        // collect codec specific data and amend the output
1004                        // format as necessary.
1005                        mFlags |= kFlagGatherCodecSpecificData;
1006                    } else if (mFlags & kFlagIsAsync) {
1007                        onOutputFormatChanged();
1008                    } else {
1009                        mFlags |= kFlagOutputFormatChanged;
1010                        postActivityNotificationIfPossible();
1011                    }
1012                    break;
1013                }
1014
1015                case CodecBase::kWhatFillThisBuffer:
1016                {
1017                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1018
1019                    if (mState == FLUSHING
1020                            || mState == STOPPING
1021                            || mState == RELEASING) {
1022                        returnBuffersToCodecOnPort(kPortIndexInput);
1023                        break;
1024                    }
1025
1026                    if (!mCSD.empty()) {
1027                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1028                        CHECK_GE(index, 0);
1029
1030                        // If codec specific data had been specified as
1031                        // part of the format in the call to configure and
1032                        // if there's more csd left, we submit it here
1033                        // clients only get access to input buffers once
1034                        // this data has been exhausted.
1035
1036                        status_t err = queueCSDInputBuffer(index);
1037
1038                        if (err != OK) {
1039                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1040                                  err);
1041
1042                            setStickyError(err);
1043                            postActivityNotificationIfPossible();
1044
1045                            cancelPendingDequeueOperations();
1046                        }
1047                        break;
1048                    }
1049
1050                    if (mFlags & kFlagIsAsync) {
1051                        if (!mHaveInputSurface) {
1052                            onInputBufferAvailable();
1053                        }
1054                    } else if (mFlags & kFlagDequeueInputPending) {
1055                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1056
1057                        ++mDequeueInputTimeoutGeneration;
1058                        mFlags &= ~kFlagDequeueInputPending;
1059                        mDequeueInputReplyID = 0;
1060                    } else {
1061                        postActivityNotificationIfPossible();
1062                    }
1063                    break;
1064                }
1065
1066                case CodecBase::kWhatDrainThisBuffer:
1067                {
1068                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1069
1070                    if (mState == FLUSHING
1071                            || mState == STOPPING
1072                            || mState == RELEASING) {
1073                        returnBuffersToCodecOnPort(kPortIndexOutput);
1074                        break;
1075                    }
1076
1077                    sp<ABuffer> buffer;
1078                    CHECK(msg->findBuffer("buffer", &buffer));
1079
1080                    int32_t omxFlags;
1081                    CHECK(msg->findInt32("flags", &omxFlags));
1082
1083                    buffer->meta()->setInt32("omxFlags", omxFlags);
1084
1085                    if (mFlags & kFlagGatherCodecSpecificData) {
1086                        // This is the very first output buffer after a
1087                        // format change was signalled, it'll either contain
1088                        // the one piece of codec specific data we can expect
1089                        // or there won't be codec specific data.
1090                        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1091                            status_t err =
1092                                amendOutputFormatWithCodecSpecificData(buffer);
1093
1094                            if (err != OK) {
1095                                ALOGE("Codec spit out malformed codec "
1096                                      "specific data!");
1097                            }
1098                        }
1099
1100                        mFlags &= ~kFlagGatherCodecSpecificData;
1101                        if (mFlags & kFlagIsAsync) {
1102                            onOutputFormatChanged();
1103                        } else {
1104                            mFlags |= kFlagOutputFormatChanged;
1105                        }
1106                    }
1107
1108                    if (mFlags & kFlagIsAsync) {
1109                        onOutputBufferAvailable();
1110                    } else if (mFlags & kFlagDequeueOutputPending) {
1111                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1112
1113                        ++mDequeueOutputTimeoutGeneration;
1114                        mFlags &= ~kFlagDequeueOutputPending;
1115                        mDequeueOutputReplyID = 0;
1116                    } else {
1117                        postActivityNotificationIfPossible();
1118                    }
1119
1120                    break;
1121                }
1122
1123                case CodecBase::kWhatEOS:
1124                {
1125                    // We already notify the client of this by using the
1126                    // corresponding flag in "onOutputBufferReady".
1127                    break;
1128                }
1129
1130                case CodecBase::kWhatShutdownCompleted:
1131                {
1132                    if (mState == STOPPING) {
1133                        setState(INITIALIZED);
1134                    } else {
1135                        CHECK_EQ(mState, RELEASING);
1136                        setState(UNINITIALIZED);
1137                        mComponentName.clear();
1138                    }
1139
1140                    (new AMessage)->postReply(mReplyID);
1141                    break;
1142                }
1143
1144                case CodecBase::kWhatFlushCompleted:
1145                {
1146                    if (mState != FLUSHING) {
1147                        ALOGW("received FlushCompleted message in state %d",
1148                                mState);
1149                        break;
1150                    }
1151
1152                    if (mFlags & kFlagIsAsync) {
1153                        setState(FLUSHED);
1154                    } else {
1155                        setState(STARTED);
1156                        mCodec->signalResume();
1157                    }
1158
1159                    (new AMessage)->postReply(mReplyID);
1160                    break;
1161                }
1162
1163                default:
1164                    TRESPASS();
1165            }
1166            break;
1167        }
1168
1169        case kWhatInit:
1170        {
1171            uint32_t replyID;
1172            CHECK(msg->senderAwaitsResponse(&replyID));
1173
1174            if (mState != UNINITIALIZED) {
1175                PostReplyWithError(replyID, INVALID_OPERATION);
1176                break;
1177            }
1178
1179            mReplyID = replyID;
1180            setState(INITIALIZING);
1181
1182            AString name;
1183            CHECK(msg->findString("name", &name));
1184
1185            int32_t nameIsType;
1186            int32_t encoder = false;
1187            CHECK(msg->findInt32("nameIsType", &nameIsType));
1188            if (nameIsType) {
1189                CHECK(msg->findInt32("encoder", &encoder));
1190            }
1191
1192            sp<AMessage> format = new AMessage;
1193
1194            if (nameIsType) {
1195                format->setString("mime", name.c_str());
1196                format->setInt32("encoder", encoder);
1197            } else {
1198                format->setString("componentName", name.c_str());
1199            }
1200
1201            mCodec->initiateAllocateComponent(format);
1202            break;
1203        }
1204
1205        case kWhatSetCallback:
1206        {
1207            uint32_t replyID;
1208            CHECK(msg->senderAwaitsResponse(&replyID));
1209
1210            if (mState == UNINITIALIZED
1211                    || mState == INITIALIZING
1212                    || isExecuting()) {
1213                // callback can't be set after codec is executing,
1214                // or before it's initialized (as the callback
1215                // will be cleared when it goes to INITIALIZED)
1216                PostReplyWithError(replyID, INVALID_OPERATION);
1217                break;
1218            }
1219
1220            sp<AMessage> callback;
1221            CHECK(msg->findMessage("callback", &callback));
1222
1223            mCallback = callback;
1224
1225            if (mCallback != NULL) {
1226                ALOGI("MediaCodec will operate in async mode");
1227                mFlags |= kFlagIsAsync;
1228            } else {
1229                mFlags &= ~kFlagIsAsync;
1230            }
1231
1232            sp<AMessage> response = new AMessage;
1233            response->postReply(replyID);
1234            break;
1235        }
1236
1237        case kWhatConfigure:
1238        {
1239            uint32_t replyID;
1240            CHECK(msg->senderAwaitsResponse(&replyID));
1241
1242            if (mState != INITIALIZED) {
1243                PostReplyWithError(replyID, INVALID_OPERATION);
1244                break;
1245            }
1246
1247            sp<RefBase> obj;
1248            if (!msg->findObject("native-window", &obj)) {
1249                obj.clear();
1250            }
1251
1252            sp<AMessage> format;
1253            CHECK(msg->findMessage("format", &format));
1254
1255            if (obj != NULL) {
1256                format->setObject("native-window", obj);
1257
1258                status_t err = setNativeWindow(
1259                    static_cast<NativeWindowWrapper *>(obj.get())
1260                        ->getSurfaceTextureClient());
1261
1262                if (err != OK) {
1263                    PostReplyWithError(replyID, err);
1264                    break;
1265                }
1266            } else {
1267                setNativeWindow(NULL);
1268            }
1269
1270            mReplyID = replyID;
1271            setState(CONFIGURING);
1272
1273            void *crypto;
1274            if (!msg->findPointer("crypto", &crypto)) {
1275                crypto = NULL;
1276            }
1277
1278            mCrypto = static_cast<ICrypto *>(crypto);
1279
1280            uint32_t flags;
1281            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1282
1283            if (flags & CONFIGURE_FLAG_ENCODE) {
1284                format->setInt32("encoder", true);
1285                mFlags |= kFlagIsEncoder;
1286            }
1287
1288            extractCSD(format);
1289
1290            mCodec->initiateConfigureComponent(format);
1291            break;
1292        }
1293
1294        case kWhatCreateInputSurface:
1295        {
1296            uint32_t replyID;
1297            CHECK(msg->senderAwaitsResponse(&replyID));
1298
1299            // Must be configured, but can't have been started yet.
1300            if (mState != CONFIGURED) {
1301                PostReplyWithError(replyID, INVALID_OPERATION);
1302                break;
1303            }
1304
1305            mReplyID = replyID;
1306            mCodec->initiateCreateInputSurface();
1307            break;
1308        }
1309
1310        case kWhatStart:
1311        {
1312            uint32_t replyID;
1313            CHECK(msg->senderAwaitsResponse(&replyID));
1314
1315            if (mState == FLUSHED) {
1316                mCodec->signalResume();
1317                PostReplyWithError(replyID, OK);
1318            } else if (mState != CONFIGURED) {
1319                PostReplyWithError(replyID, INVALID_OPERATION);
1320                break;
1321            }
1322
1323            mReplyID = replyID;
1324            setState(STARTING);
1325
1326            mCodec->initiateStart();
1327            break;
1328        }
1329
1330        case kWhatStop:
1331        case kWhatRelease:
1332        {
1333            State targetState =
1334                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1335
1336            uint32_t replyID;
1337            CHECK(msg->senderAwaitsResponse(&replyID));
1338
1339            if (mState != INITIALIZED
1340                    && mState != CONFIGURED && !isExecuting()) {
1341                // We may be in "UNINITIALIZED" state already without the
1342                // client being aware of this if media server died while
1343                // we were being stopped. The client would assume that
1344                // after stop() returned, it would be safe to call release()
1345                // and it should be in this case, no harm to allow a release()
1346                // if we're already uninitialized.
1347                sp<AMessage> response = new AMessage;
1348                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1349                response->setInt32("err", err);
1350                if (err == OK && targetState == UNINITIALIZED) {
1351                    mComponentName.clear();
1352                }
1353                response->postReply(replyID);
1354                break;
1355            }
1356
1357            if (mFlags & kFlagSawMediaServerDie) {
1358                // It's dead, Jim. Don't expect initiateShutdown to yield
1359                // any useful results now...
1360                setState(UNINITIALIZED);
1361                if (targetState == UNINITIALIZED) {
1362                    mComponentName.clear();
1363                }
1364                (new AMessage)->postReply(replyID);
1365                break;
1366            }
1367
1368            mReplyID = replyID;
1369            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1370
1371            mCodec->initiateShutdown(
1372                    msg->what() == kWhatStop /* keepComponentAllocated */);
1373
1374            returnBuffersToCodec();
1375            break;
1376        }
1377
1378        case kWhatDequeueInputBuffer:
1379        {
1380            uint32_t replyID;
1381            CHECK(msg->senderAwaitsResponse(&replyID));
1382
1383            if (mFlags & kFlagIsAsync) {
1384                ALOGE("dequeueOutputBuffer can't be used in async mode");
1385                PostReplyWithError(replyID, INVALID_OPERATION);
1386                break;
1387            }
1388
1389            if (mHaveInputSurface) {
1390                ALOGE("dequeueInputBuffer can't be used with input surface");
1391                PostReplyWithError(replyID, INVALID_OPERATION);
1392                break;
1393            }
1394
1395            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1396                break;
1397            }
1398
1399            int64_t timeoutUs;
1400            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1401
1402            if (timeoutUs == 0ll) {
1403                PostReplyWithError(replyID, -EAGAIN);
1404                break;
1405            }
1406
1407            mFlags |= kFlagDequeueInputPending;
1408            mDequeueInputReplyID = replyID;
1409
1410            if (timeoutUs > 0ll) {
1411                sp<AMessage> timeoutMsg =
1412                    new AMessage(kWhatDequeueInputTimedOut, id());
1413                timeoutMsg->setInt32(
1414                        "generation", ++mDequeueInputTimeoutGeneration);
1415                timeoutMsg->post(timeoutUs);
1416            }
1417            break;
1418        }
1419
1420        case kWhatDequeueInputTimedOut:
1421        {
1422            int32_t generation;
1423            CHECK(msg->findInt32("generation", &generation));
1424
1425            if (generation != mDequeueInputTimeoutGeneration) {
1426                // Obsolete
1427                break;
1428            }
1429
1430            CHECK(mFlags & kFlagDequeueInputPending);
1431
1432            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
1433
1434            mFlags &= ~kFlagDequeueInputPending;
1435            mDequeueInputReplyID = 0;
1436            break;
1437        }
1438
1439        case kWhatQueueInputBuffer:
1440        {
1441            uint32_t replyID;
1442            CHECK(msg->senderAwaitsResponse(&replyID));
1443
1444            if (!isExecuting()) {
1445                PostReplyWithError(replyID, INVALID_OPERATION);
1446                break;
1447            } else if (mFlags & kFlagStickyError) {
1448                PostReplyWithError(replyID, getStickyError());
1449                break;
1450            }
1451
1452            status_t err = onQueueInputBuffer(msg);
1453
1454            PostReplyWithError(replyID, err);
1455            break;
1456        }
1457
1458        case kWhatDequeueOutputBuffer:
1459        {
1460            uint32_t replyID;
1461            CHECK(msg->senderAwaitsResponse(&replyID));
1462
1463            if (mFlags & kFlagIsAsync) {
1464                ALOGE("dequeueOutputBuffer can't be used in async mode");
1465                PostReplyWithError(replyID, INVALID_OPERATION);
1466                break;
1467            }
1468
1469            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1470                break;
1471            }
1472
1473            int64_t timeoutUs;
1474            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1475
1476            if (timeoutUs == 0ll) {
1477                PostReplyWithError(replyID, -EAGAIN);
1478                break;
1479            }
1480
1481            mFlags |= kFlagDequeueOutputPending;
1482            mDequeueOutputReplyID = replyID;
1483
1484            if (timeoutUs > 0ll) {
1485                sp<AMessage> timeoutMsg =
1486                    new AMessage(kWhatDequeueOutputTimedOut, id());
1487                timeoutMsg->setInt32(
1488                        "generation", ++mDequeueOutputTimeoutGeneration);
1489                timeoutMsg->post(timeoutUs);
1490            }
1491            break;
1492        }
1493
1494        case kWhatDequeueOutputTimedOut:
1495        {
1496            int32_t generation;
1497            CHECK(msg->findInt32("generation", &generation));
1498
1499            if (generation != mDequeueOutputTimeoutGeneration) {
1500                // Obsolete
1501                break;
1502            }
1503
1504            CHECK(mFlags & kFlagDequeueOutputPending);
1505
1506            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
1507
1508            mFlags &= ~kFlagDequeueOutputPending;
1509            mDequeueOutputReplyID = 0;
1510            break;
1511        }
1512
1513        case kWhatReleaseOutputBuffer:
1514        {
1515            uint32_t replyID;
1516            CHECK(msg->senderAwaitsResponse(&replyID));
1517
1518            if (!isExecuting()) {
1519                PostReplyWithError(replyID, INVALID_OPERATION);
1520                break;
1521            } else if (mFlags & kFlagStickyError) {
1522                PostReplyWithError(replyID, getStickyError());
1523                break;
1524            }
1525
1526            status_t err = onReleaseOutputBuffer(msg);
1527
1528            PostReplyWithError(replyID, err);
1529            break;
1530        }
1531
1532        case kWhatSignalEndOfInputStream:
1533        {
1534            uint32_t replyID;
1535            CHECK(msg->senderAwaitsResponse(&replyID));
1536
1537            if (!isExecuting()) {
1538                PostReplyWithError(replyID, INVALID_OPERATION);
1539                break;
1540            } else if (mFlags & kFlagStickyError) {
1541                PostReplyWithError(replyID, getStickyError());
1542                break;
1543            }
1544
1545            mReplyID = replyID;
1546            mCodec->signalEndOfInputStream();
1547            break;
1548        }
1549
1550        case kWhatGetBuffers:
1551        {
1552            uint32_t replyID;
1553            CHECK(msg->senderAwaitsResponse(&replyID));
1554
1555            if (!isExecuting() || (mFlags & kFlagIsAsync)) {
1556                PostReplyWithError(replyID, INVALID_OPERATION);
1557                break;
1558            } else if (mFlags & kFlagStickyError) {
1559                PostReplyWithError(replyID, getStickyError());
1560                break;
1561            }
1562
1563            int32_t portIndex;
1564            CHECK(msg->findInt32("portIndex", &portIndex));
1565
1566            Vector<sp<ABuffer> > *dstBuffers;
1567            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1568
1569            dstBuffers->clear();
1570            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1571
1572            for (size_t i = 0; i < srcBuffers.size(); ++i) {
1573                const BufferInfo &info = srcBuffers.itemAt(i);
1574
1575                dstBuffers->push_back(
1576                        (portIndex == kPortIndexInput && mCrypto != NULL)
1577                                ? info.mEncryptedData : info.mData);
1578            }
1579
1580            (new AMessage)->postReply(replyID);
1581            break;
1582        }
1583
1584        case kWhatFlush:
1585        {
1586            uint32_t replyID;
1587            CHECK(msg->senderAwaitsResponse(&replyID));
1588
1589            if (!isExecuting()) {
1590                PostReplyWithError(replyID, INVALID_OPERATION);
1591                break;
1592            } else if (mFlags & kFlagStickyError) {
1593                PostReplyWithError(replyID, getStickyError());
1594                break;
1595            }
1596
1597            mReplyID = replyID;
1598            // TODO: skip flushing if already FLUSHED
1599            setState(FLUSHING);
1600
1601            mCodec->signalFlush();
1602            returnBuffersToCodec();
1603            break;
1604        }
1605
1606        case kWhatGetInputFormat:
1607        case kWhatGetOutputFormat:
1608        {
1609            sp<AMessage> format =
1610                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
1611
1612            uint32_t replyID;
1613            CHECK(msg->senderAwaitsResponse(&replyID));
1614
1615            if ((mState != CONFIGURED && mState != STARTING &&
1616                 mState != STARTED && mState != FLUSHING &&
1617                 mState != FLUSHED)
1618                    || format == NULL) {
1619                PostReplyWithError(replyID, INVALID_OPERATION);
1620                break;
1621            } else if (mFlags & kFlagStickyError) {
1622                PostReplyWithError(replyID, getStickyError());
1623                break;
1624            }
1625
1626            sp<AMessage> response = new AMessage;
1627            response->setMessage("format", format);
1628            response->postReply(replyID);
1629            break;
1630        }
1631
1632        case kWhatRequestIDRFrame:
1633        {
1634            mCodec->signalRequestIDRFrame();
1635            break;
1636        }
1637
1638        case kWhatRequestActivityNotification:
1639        {
1640            CHECK(mActivityNotify == NULL);
1641            CHECK(msg->findMessage("notify", &mActivityNotify));
1642
1643            postActivityNotificationIfPossible();
1644            break;
1645        }
1646
1647        case kWhatGetName:
1648        {
1649            uint32_t replyID;
1650            CHECK(msg->senderAwaitsResponse(&replyID));
1651
1652            if (mComponentName.empty()) {
1653                PostReplyWithError(replyID, INVALID_OPERATION);
1654                break;
1655            }
1656
1657            sp<AMessage> response = new AMessage;
1658            response->setString("name", mComponentName.c_str());
1659            response->postReply(replyID);
1660            break;
1661        }
1662
1663        case kWhatSetParameters:
1664        {
1665            uint32_t replyID;
1666            CHECK(msg->senderAwaitsResponse(&replyID));
1667
1668            sp<AMessage> params;
1669            CHECK(msg->findMessage("params", &params));
1670
1671            status_t err = onSetParameters(params);
1672
1673            PostReplyWithError(replyID, err);
1674            break;
1675        }
1676
1677        default:
1678            TRESPASS();
1679    }
1680}
1681
1682void MediaCodec::extractCSD(const sp<AMessage> &format) {
1683    mCSD.clear();
1684
1685    size_t i = 0;
1686    for (;;) {
1687        sp<ABuffer> csd;
1688        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
1689            break;
1690        }
1691
1692        mCSD.push_back(csd);
1693        ++i;
1694    }
1695
1696    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
1697}
1698
1699status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1700    CHECK(!mCSD.empty());
1701
1702    const BufferInfo *info =
1703        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
1704
1705    sp<ABuffer> csd = *mCSD.begin();
1706    mCSD.erase(mCSD.begin());
1707
1708    const sp<ABuffer> &codecInputData =
1709        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1710
1711    if (csd->size() > codecInputData->capacity()) {
1712        return -EINVAL;
1713    }
1714
1715    memcpy(codecInputData->data(), csd->data(), csd->size());
1716
1717    AString errorDetailMsg;
1718
1719    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1720    msg->setSize("index", bufferIndex);
1721    msg->setSize("offset", 0);
1722    msg->setSize("size", csd->size());
1723    msg->setInt64("timeUs", 0ll);
1724    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1725    msg->setPointer("errorDetailMsg", &errorDetailMsg);
1726
1727    return onQueueInputBuffer(msg);
1728}
1729
1730void MediaCodec::setState(State newState) {
1731    if (newState == INITIALIZED || newState == UNINITIALIZED) {
1732        delete mSoftRenderer;
1733        mSoftRenderer = NULL;
1734
1735        mCrypto.clear();
1736        setNativeWindow(NULL);
1737
1738        mInputFormat.clear();
1739        mOutputFormat.clear();
1740        mFlags &= ~kFlagOutputFormatChanged;
1741        mFlags &= ~kFlagOutputBuffersChanged;
1742        mFlags &= ~kFlagStickyError;
1743        mFlags &= ~kFlagIsEncoder;
1744        mFlags &= ~kFlagGatherCodecSpecificData;
1745        mFlags &= ~kFlagIsAsync;
1746        mStickyError = OK;
1747
1748        mActivityNotify.clear();
1749        mCallback.clear();
1750    }
1751
1752    if (newState == UNINITIALIZED) {
1753        // return any straggling buffers, e.g. if we got here on an error
1754        returnBuffersToCodec();
1755
1756        // The component is gone, mediaserver's probably back up already
1757        // but should definitely be back up should we try to instantiate
1758        // another component.. and the cycle continues.
1759        mFlags &= ~kFlagSawMediaServerDie;
1760    }
1761
1762    mState = newState;
1763
1764    cancelPendingDequeueOperations();
1765
1766    updateBatteryStat();
1767}
1768
1769void MediaCodec::returnBuffersToCodec() {
1770    returnBuffersToCodecOnPort(kPortIndexInput);
1771    returnBuffersToCodecOnPort(kPortIndexOutput);
1772}
1773
1774void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1775    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1776    Mutex::Autolock al(mBufferLock);
1777
1778    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1779
1780    for (size_t i = 0; i < buffers->size(); ++i) {
1781        BufferInfo *info = &buffers->editItemAt(i);
1782
1783        if (info->mNotify != NULL) {
1784            sp<AMessage> msg = info->mNotify;
1785            info->mNotify = NULL;
1786            info->mOwnedByClient = false;
1787
1788            if (portIndex == kPortIndexInput) {
1789                /* no error, just returning buffers */
1790                msg->setInt32("err", OK);
1791            }
1792            msg->post();
1793        }
1794    }
1795
1796    mAvailPortBuffers[portIndex].clear();
1797}
1798
1799size_t MediaCodec::updateBuffers(
1800        int32_t portIndex, const sp<AMessage> &msg) {
1801    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1802
1803    uint32_t bufferID;
1804    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
1805
1806    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1807
1808    for (size_t i = 0; i < buffers->size(); ++i) {
1809        BufferInfo *info = &buffers->editItemAt(i);
1810
1811        if (info->mBufferID == bufferID) {
1812            CHECK(info->mNotify == NULL);
1813            CHECK(msg->findMessage("reply", &info->mNotify));
1814
1815            info->mFormat =
1816                (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
1817            mAvailPortBuffers[portIndex].push_back(i);
1818
1819            return i;
1820        }
1821    }
1822
1823    TRESPASS();
1824
1825    return 0;
1826}
1827
1828status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1829    size_t index;
1830    size_t offset;
1831    size_t size;
1832    int64_t timeUs;
1833    uint32_t flags;
1834    CHECK(msg->findSize("index", &index));
1835    CHECK(msg->findSize("offset", &offset));
1836    CHECK(msg->findInt64("timeUs", &timeUs));
1837    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1838
1839    const CryptoPlugin::SubSample *subSamples;
1840    size_t numSubSamples;
1841    const uint8_t *key;
1842    const uint8_t *iv;
1843    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1844
1845    // We allow the simpler queueInputBuffer API to be used even in
1846    // secure mode, by fabricating a single unencrypted subSample.
1847    CryptoPlugin::SubSample ss;
1848
1849    if (msg->findSize("size", &size)) {
1850        if (mCrypto != NULL) {
1851            ss.mNumBytesOfClearData = size;
1852            ss.mNumBytesOfEncryptedData = 0;
1853
1854            subSamples = &ss;
1855            numSubSamples = 1;
1856            key = NULL;
1857            iv = NULL;
1858        }
1859    } else {
1860        if (mCrypto == NULL) {
1861            return -EINVAL;
1862        }
1863
1864        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1865        CHECK(msg->findSize("numSubSamples", &numSubSamples));
1866        CHECK(msg->findPointer("key", (void **)&key));
1867        CHECK(msg->findPointer("iv", (void **)&iv));
1868
1869        int32_t tmp;
1870        CHECK(msg->findInt32("mode", &tmp));
1871
1872        mode = (CryptoPlugin::Mode)tmp;
1873
1874        size = 0;
1875        for (size_t i = 0; i < numSubSamples; ++i) {
1876            size += subSamples[i].mNumBytesOfClearData;
1877            size += subSamples[i].mNumBytesOfEncryptedData;
1878        }
1879    }
1880
1881    if (index >= mPortBuffers[kPortIndexInput].size()) {
1882        return -ERANGE;
1883    }
1884
1885    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1886
1887    if (info->mNotify == NULL || !info->mOwnedByClient) {
1888        return -EACCES;
1889    }
1890
1891    if (offset + size > info->mData->capacity()) {
1892        return -EINVAL;
1893    }
1894
1895    sp<AMessage> reply = info->mNotify;
1896    info->mData->setRange(offset, size);
1897    info->mData->meta()->setInt64("timeUs", timeUs);
1898
1899    if (flags & BUFFER_FLAG_EOS) {
1900        info->mData->meta()->setInt32("eos", true);
1901    }
1902
1903    if (flags & BUFFER_FLAG_CODECCONFIG) {
1904        info->mData->meta()->setInt32("csd", true);
1905    }
1906
1907    if (mCrypto != NULL) {
1908        if (size > info->mEncryptedData->capacity()) {
1909            return -ERANGE;
1910        }
1911
1912        AString *errorDetailMsg;
1913        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1914
1915        ssize_t result = mCrypto->decrypt(
1916                (mFlags & kFlagIsSecure) != 0,
1917                key,
1918                iv,
1919                mode,
1920                info->mEncryptedData->base() + offset,
1921                subSamples,
1922                numSubSamples,
1923                info->mData->base(),
1924                errorDetailMsg);
1925
1926        if (result < 0) {
1927            return result;
1928        }
1929
1930        info->mData->setRange(0, result);
1931    }
1932
1933    // synchronization boundary for getBufferAndFormat
1934    {
1935        Mutex::Autolock al(mBufferLock);
1936        info->mOwnedByClient = false;
1937    }
1938    reply->setBuffer("buffer", info->mData);
1939    reply->post();
1940
1941    info->mNotify = NULL;
1942
1943    return OK;
1944}
1945
1946status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1947    size_t index;
1948    CHECK(msg->findSize("index", &index));
1949
1950    int32_t render;
1951    if (!msg->findInt32("render", &render)) {
1952        render = 0;
1953    }
1954
1955    if (!isExecuting()) {
1956        return -EINVAL;
1957    }
1958
1959    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1960        return -ERANGE;
1961    }
1962
1963    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1964
1965    if (info->mNotify == NULL || !info->mOwnedByClient) {
1966        return -EACCES;
1967    }
1968
1969    // synchronization boundary for getBufferAndFormat
1970    {
1971        Mutex::Autolock al(mBufferLock);
1972        info->mOwnedByClient = false;
1973    }
1974
1975    if (render && info->mData != NULL && info->mData->size() != 0) {
1976        info->mNotify->setInt32("render", true);
1977
1978        int64_t timestampNs = 0;
1979        if (msg->findInt64("timestampNs", &timestampNs)) {
1980            info->mNotify->setInt64("timestampNs", timestampNs);
1981        } else {
1982            // TODO: it seems like we should use the timestamp
1983            // in the (media)buffer as it potentially came from
1984            // an input surface, but we did not propagate it prior to
1985            // API 20.  Perhaps check for target SDK version.
1986#if 0
1987            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
1988                ALOGV("using buffer PTS of %" PRId64, timestampNs);
1989                timestampNs *= 1000;
1990            }
1991#endif
1992        }
1993
1994        if (mSoftRenderer != NULL) {
1995            mSoftRenderer->render(
1996                    info->mData->data(), info->mData->size(),
1997                    timestampNs, NULL, info->mFormat);
1998        }
1999    }
2000
2001    info->mNotify->post();
2002    info->mNotify = NULL;
2003
2004    return OK;
2005}
2006
2007ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2008    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2009
2010    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2011
2012    if (availBuffers->empty()) {
2013        return -EAGAIN;
2014    }
2015
2016    size_t index = *availBuffers->begin();
2017    availBuffers->erase(availBuffers->begin());
2018
2019    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2020    CHECK(!info->mOwnedByClient);
2021    {
2022        Mutex::Autolock al(mBufferLock);
2023        info->mOwnedByClient = true;
2024
2025        // set image-data
2026        if (info->mFormat != NULL) {
2027            sp<ABuffer> imageData;
2028            if (info->mFormat->findBuffer("image-data", &imageData)) {
2029                info->mData->meta()->setBuffer("image-data", imageData);
2030            }
2031            int32_t left, top, right, bottom;
2032            if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2033                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2034            }
2035        }
2036    }
2037
2038    return index;
2039}
2040
2041status_t MediaCodec::setNativeWindow(
2042        const sp<Surface> &surfaceTextureClient) {
2043    status_t err;
2044
2045    if (mNativeWindow != NULL) {
2046        err = native_window_api_disconnect(
2047                mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
2048
2049        if (err != OK) {
2050            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
2051                    strerror(-err), err);
2052        }
2053
2054        mNativeWindow.clear();
2055    }
2056
2057    if (surfaceTextureClient != NULL) {
2058        err = native_window_api_connect(
2059                surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
2060
2061        if (err != OK) {
2062            ALOGE("native_window_api_connect returned an error: %s (%d)",
2063                    strerror(-err), err);
2064
2065            return err;
2066        }
2067
2068        mNativeWindow = surfaceTextureClient;
2069    }
2070
2071    return OK;
2072}
2073
2074void MediaCodec::onInputBufferAvailable() {
2075    int32_t index;
2076    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2077        sp<AMessage> msg = mCallback->dup();
2078        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2079        msg->setInt32("index", index);
2080        msg->post();
2081    }
2082}
2083
2084void MediaCodec::onOutputBufferAvailable() {
2085    int32_t index;
2086    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2087        const sp<ABuffer> &buffer =
2088            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2089        sp<AMessage> msg = mCallback->dup();
2090        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2091        msg->setInt32("index", index);
2092        msg->setSize("offset", buffer->offset());
2093        msg->setSize("size", buffer->size());
2094
2095        int64_t timeUs;
2096        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2097
2098        msg->setInt64("timeUs", timeUs);
2099
2100        int32_t omxFlags;
2101        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2102
2103        uint32_t flags = 0;
2104        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2105            flags |= BUFFER_FLAG_SYNCFRAME;
2106        }
2107        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2108            flags |= BUFFER_FLAG_CODECCONFIG;
2109        }
2110        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2111            flags |= BUFFER_FLAG_EOS;
2112        }
2113
2114        msg->setInt32("flags", flags);
2115
2116        msg->post();
2117    }
2118}
2119
2120void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2121    if (mCallback != NULL) {
2122        sp<AMessage> msg = mCallback->dup();
2123        msg->setInt32("callbackID", CB_ERROR);
2124        msg->setInt32("err", err);
2125        msg->setInt32("actionCode", actionCode);
2126
2127        if (detail != NULL) {
2128            msg->setString("detail", detail);
2129        }
2130
2131        msg->post();
2132    }
2133}
2134
2135void MediaCodec::onOutputFormatChanged() {
2136    if (mCallback != NULL) {
2137        sp<AMessage> msg = mCallback->dup();
2138        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2139        msg->setMessage("format", mOutputFormat);
2140        msg->post();
2141    }
2142}
2143
2144
2145void MediaCodec::postActivityNotificationIfPossible() {
2146    if (mActivityNotify == NULL) {
2147        return;
2148    }
2149
2150    bool isErrorOrOutputChanged =
2151            (mFlags & (kFlagStickyError
2152                    | kFlagOutputBuffersChanged
2153                    | kFlagOutputFormatChanged));
2154
2155    if (isErrorOrOutputChanged
2156            || !mAvailPortBuffers[kPortIndexInput].empty()
2157            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2158        mActivityNotify->setInt32("input-buffers",
2159                mAvailPortBuffers[kPortIndexInput].size());
2160
2161        if (isErrorOrOutputChanged) {
2162            // we want consumer to dequeue as many times as it can
2163            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2164        } else {
2165            mActivityNotify->setInt32("output-buffers",
2166                    mAvailPortBuffers[kPortIndexOutput].size());
2167        }
2168        mActivityNotify->post();
2169        mActivityNotify.clear();
2170    }
2171}
2172
2173status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2174    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
2175    msg->setMessage("params", params);
2176
2177    sp<AMessage> response;
2178    return PostAndAwaitResponse(msg, &response);
2179}
2180
2181status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2182    mCodec->signalSetParameters(params);
2183
2184    return OK;
2185}
2186
2187status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2188        const sp<ABuffer> &buffer) {
2189    AString mime;
2190    CHECK(mOutputFormat->findString("mime", &mime));
2191
2192    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2193        // Codec specific data should be SPS and PPS in a single buffer,
2194        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2195        // We separate the two and put them into the output format
2196        // under the keys "csd-0" and "csd-1".
2197
2198        unsigned csdIndex = 0;
2199
2200        const uint8_t *data = buffer->data();
2201        size_t size = buffer->size();
2202
2203        const uint8_t *nalStart;
2204        size_t nalSize;
2205        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2206            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2207            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2208            memcpy(csd->data() + 4, nalStart, nalSize);
2209
2210            mOutputFormat->setBuffer(
2211                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2212
2213            ++csdIndex;
2214        }
2215
2216        if (csdIndex != 2) {
2217            return ERROR_MALFORMED;
2218        }
2219    } else {
2220        // For everything else we just stash the codec specific data into
2221        // the output format as a single piece of csd under "csd-0".
2222        mOutputFormat->setBuffer("csd-0", buffer);
2223    }
2224
2225    return OK;
2226}
2227
2228void MediaCodec::updateBatteryStat() {
2229    if (mState == CONFIGURED && !mBatteryStatNotified) {
2230        AString mime;
2231        CHECK(mOutputFormat != NULL &&
2232                mOutputFormat->findString("mime", &mime));
2233
2234        mIsVideo = mime.startsWithIgnoreCase("video/");
2235
2236        BatteryNotifier& notifier(BatteryNotifier::getInstance());
2237
2238        if (mIsVideo) {
2239            notifier.noteStartVideo();
2240        } else {
2241            notifier.noteStartAudio();
2242        }
2243
2244        mBatteryStatNotified = true;
2245    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2246        BatteryNotifier& notifier(BatteryNotifier::getInstance());
2247
2248        if (mIsVideo) {
2249            notifier.noteStopVideo();
2250        } else {
2251            notifier.noteStopAudio();
2252        }
2253
2254        mBatteryStatNotified = false;
2255    }
2256}
2257
2258}  // namespace android
2259