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