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