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