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