MediaCodec.cpp revision 349b8b4c47817a565ded94ff351caf48782f1252
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/SecureBuffer.h"
23#include "include/SharedMemoryBuffer.h"
24#include "include/SoftwareRenderer.h"
25
26#include <binder/IMemory.h>
27#include <binder/IPCThreadState.h>
28#include <binder/IServiceManager.h>
29#include <binder/MemoryDealer.h>
30#include <gui/BufferQueue.h>
31#include <gui/Surface.h>
32#include <media/ICrypto.h>
33#include <media/IOMX.h>
34#include <media/IResourceManagerService.h>
35#include <media/MediaCodecBuffer.h>
36#include <media/stagefright/foundation/ABuffer.h>
37#include <media/stagefright/foundation/ADebug.h>
38#include <media/stagefright/foundation/AMessage.h>
39#include <media/stagefright/foundation/AString.h>
40#include <media/stagefright/foundation/hexdump.h>
41#include <media/stagefright/ACodec.h>
42#include <media/stagefright/BufferProducerWrapper.h>
43#include <media/stagefright/MediaCodec.h>
44#include <media/stagefright/MediaCodecList.h>
45#include <media/stagefright/MediaDefs.h>
46#include <media/stagefright/MediaErrors.h>
47#include <media/stagefright/MediaFilter.h>
48#include <media/stagefright/MetaData.h>
49#include <media/stagefright/OMXClient.h>
50#include <media/stagefright/PersistentSurface.h>
51#include <media/stagefright/SurfaceUtils.h>
52#include <mediautils/BatteryNotifier.h>
53#include <private/android_filesystem_config.h>
54#include <utils/Log.h>
55#include <utils/Singleton.h>
56
57namespace android {
58
59static int64_t getId(const sp<IResourceManagerClient> &client) {
60    return (int64_t) client.get();
61}
62
63static bool isResourceError(status_t err) {
64    return (err == NO_MEMORY);
65}
66
67static const int kMaxRetry = 2;
68static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
69
70struct ResourceManagerClient : public BnResourceManagerClient {
71    explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
72
73    virtual bool reclaimResource() {
74        sp<MediaCodec> codec = mMediaCodec.promote();
75        if (codec == NULL) {
76            // codec is already gone.
77            return true;
78        }
79        status_t err = codec->reclaim();
80        if (err == WOULD_BLOCK) {
81            ALOGD("Wait for the client to release codec.");
82            usleep(kMaxReclaimWaitTimeInUs);
83            ALOGD("Try to reclaim again.");
84            err = codec->reclaim(true /* force */);
85        }
86        if (err != OK) {
87            ALOGW("ResourceManagerClient failed to release codec with err %d", err);
88        }
89        return (err == OK);
90    }
91
92    virtual String8 getName() {
93        String8 ret;
94        sp<MediaCodec> codec = mMediaCodec.promote();
95        if (codec == NULL) {
96            // codec is already gone.
97            return ret;
98        }
99
100        AString name;
101        if (codec->getName(&name) == OK) {
102            ret.setTo(name.c_str());
103        }
104        return ret;
105    }
106
107protected:
108    virtual ~ResourceManagerClient() {}
109
110private:
111    wp<MediaCodec> mMediaCodec;
112
113    DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
114};
115
116MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(pid_t pid)
117        : mPid(pid) {
118    if (mPid == MediaCodec::kNoPid) {
119        mPid = IPCThreadState::self()->getCallingPid();
120    }
121}
122
123MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
124    if (mService != NULL) {
125        IInterface::asBinder(mService)->unlinkToDeath(this);
126    }
127}
128
129void MediaCodec::ResourceManagerServiceProxy::init() {
130    sp<IServiceManager> sm = defaultServiceManager();
131    sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
132    mService = interface_cast<IResourceManagerService>(binder);
133    if (mService == NULL) {
134        ALOGE("Failed to get ResourceManagerService");
135        return;
136    }
137    IInterface::asBinder(mService)->linkToDeath(this);
138}
139
140void MediaCodec::ResourceManagerServiceProxy::binderDied(const wp<IBinder>& /*who*/) {
141    ALOGW("ResourceManagerService died.");
142    Mutex::Autolock _l(mLock);
143    mService.clear();
144}
145
146void MediaCodec::ResourceManagerServiceProxy::addResource(
147        int64_t clientId,
148        const sp<IResourceManagerClient> &client,
149        const Vector<MediaResource> &resources) {
150    Mutex::Autolock _l(mLock);
151    if (mService == NULL) {
152        return;
153    }
154    mService->addResource(mPid, clientId, client, resources);
155}
156
157void MediaCodec::ResourceManagerServiceProxy::removeResource(int64_t clientId) {
158    Mutex::Autolock _l(mLock);
159    if (mService == NULL) {
160        return;
161    }
162    mService->removeResource(mPid, clientId);
163}
164
165bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
166        const Vector<MediaResource> &resources) {
167    Mutex::Autolock _l(mLock);
168    if (mService == NULL) {
169        return false;
170    }
171    return mService->reclaimResource(mPid, resources);
172}
173
174// static
175sp<MediaCodec> MediaCodec::CreateByType(
176        const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
177        uid_t uid) {
178    sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
179
180    const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
181    if (err != NULL) {
182        *err = ret;
183    }
184    return ret == OK ? codec : NULL; // NULL deallocates codec.
185}
186
187// static
188sp<MediaCodec> MediaCodec::CreateByComponentName(
189        const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
190    sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
191
192    const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
193    if (err != NULL) {
194        *err = ret;
195    }
196    return ret == OK ? codec : NULL; // NULL deallocates codec.
197}
198
199// static
200status_t MediaCodec::QueryCapabilities(
201        const AString &name, const AString &mime, bool isEncoder,
202        sp<MediaCodecInfo::Capabilities> *caps /* nonnull */) {
203    // TRICKY: this method is used by MediaCodecList/Info during its
204    // initialization. As such, we cannot create a MediaCodec instance
205    // because that requires an initialized MediaCodecList.
206
207    sp<CodecBase> codec = GetCodecBase(name);
208    if (codec == NULL) {
209        return NAME_NOT_FOUND;
210    }
211
212    return codec->queryCapabilities(name, mime, isEncoder, caps);
213}
214
215// static
216sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
217    OMXClient client;
218    if (client.connect() != OK) {
219        ALOGE("Failed to connect to OMX to create persistent input surface.");
220        return NULL;
221    }
222
223    sp<IOMX> omx = client.interface();
224
225    sp<IGraphicBufferProducer> bufferProducer;
226    sp<IGraphicBufferSource> bufferSource;
227
228    status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
229
230    if (err != OK) {
231        ALOGE("Failed to create persistent input surface.");
232        return NULL;
233    }
234
235    return new PersistentSurface(bufferProducer, bufferSource);
236}
237
238MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
239    : mState(UNINITIALIZED),
240      mReleasedByResourceManager(false),
241      mLooper(looper),
242      mCodec(NULL),
243      mReplyID(0),
244      mFlags(0),
245      mStickyError(OK),
246      mSoftRenderer(NULL),
247      mResourceManagerClient(new ResourceManagerClient(this)),
248      mResourceManagerService(new ResourceManagerServiceProxy(pid)),
249      mBatteryStatNotified(false),
250      mIsVideo(false),
251      mVideoWidth(0),
252      mVideoHeight(0),
253      mRotationDegrees(0),
254      mDequeueInputTimeoutGeneration(0),
255      mDequeueInputReplyID(0),
256      mDequeueOutputTimeoutGeneration(0),
257      mDequeueOutputReplyID(0),
258      mHaveInputSurface(false),
259      mHavePendingInputBuffers(false) {
260    if (uid == kNoUid) {
261        mUid = IPCThreadState::self()->getCallingUid();
262    } else {
263        mUid = uid;
264    }
265}
266
267MediaCodec::~MediaCodec() {
268    CHECK_EQ(mState, UNINITIALIZED);
269    mResourceManagerService->removeResource(getId(mResourceManagerClient));
270}
271
272// static
273status_t MediaCodec::PostAndAwaitResponse(
274        const sp<AMessage> &msg, sp<AMessage> *response) {
275    status_t err = msg->postAndAwaitResponse(response);
276
277    if (err != OK) {
278        return err;
279    }
280
281    if (!(*response)->findInt32("err", &err)) {
282        err = OK;
283    }
284
285    return err;
286}
287
288void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
289    int32_t finalErr = err;
290    if (mReleasedByResourceManager) {
291        // override the err code if MediaCodec has been released by ResourceManager.
292        finalErr = DEAD_OBJECT;
293    }
294
295    sp<AMessage> response = new AMessage;
296    response->setInt32("err", finalErr);
297    response->postReply(replyID);
298}
299
300//static
301sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
302    // at this time only ACodec specifies a mime type.
303    if (nameIsType || name.startsWithIgnoreCase("omx.")) {
304        return new ACodec;
305    } else if (name.startsWithIgnoreCase("android.filter.")) {
306        return new MediaFilter;
307    } else {
308        return NULL;
309    }
310}
311
312status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
313    mResourceManagerService->init();
314
315    // save init parameters for reset
316    mInitName = name;
317    mInitNameIsType = nameIsType;
318    mInitIsEncoder = encoder;
319
320    // Current video decoders do not return from OMX_FillThisBuffer
321    // quickly, violating the OpenMAX specs, until that is remedied
322    // we need to invest in an extra looper to free the main event
323    // queue.
324
325    mCodec = GetCodecBase(name, nameIsType);
326    if (mCodec == NULL) {
327        return NAME_NOT_FOUND;
328    }
329
330    bool secureCodec = false;
331    if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
332        mIsVideo = true;
333    } else {
334        AString tmp = name;
335        if (tmp.endsWith(".secure")) {
336            secureCodec = true;
337            tmp.erase(tmp.size() - 7, 7);
338        }
339        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
340        if (mcl == NULL) {
341            mCodec = NULL;  // remove the codec.
342            return NO_INIT; // if called from Java should raise IOException
343        }
344        ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
345        if (codecIdx >= 0) {
346            const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
347            Vector<AString> mimes;
348            info->getSupportedMimes(&mimes);
349            for (size_t i = 0; i < mimes.size(); i++) {
350                if (mimes[i].startsWith("video/")) {
351                    mIsVideo = true;
352                    break;
353                }
354            }
355        }
356    }
357
358    if (mIsVideo) {
359        // video codec needs dedicated looper
360        if (mCodecLooper == NULL) {
361            mCodecLooper = new ALooper;
362            mCodecLooper->setName("CodecLooper");
363            mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
364        }
365
366        mCodecLooper->registerHandler(mCodec);
367    } else {
368        mLooper->registerHandler(mCodec);
369    }
370
371    mLooper->registerHandler(this);
372
373    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, this));
374
375    sp<AMessage> msg = new AMessage(kWhatInit, this);
376    msg->setString("name", name);
377    msg->setInt32("nameIsType", nameIsType);
378
379    if (nameIsType) {
380        msg->setInt32("encoder", encoder);
381    }
382
383    status_t err;
384    Vector<MediaResource> resources;
385    MediaResource::Type type =
386            secureCodec ? MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
387    MediaResource::SubType subtype =
388            mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
389    resources.push_back(MediaResource(type, subtype, 1));
390    for (int i = 0; i <= kMaxRetry; ++i) {
391        if (i > 0) {
392            // Don't try to reclaim resource for the first time.
393            if (!mResourceManagerService->reclaimResource(resources)) {
394                break;
395            }
396        }
397
398        sp<AMessage> response;
399        err = PostAndAwaitResponse(msg, &response);
400        if (!isResourceError(err)) {
401            break;
402        }
403    }
404    return err;
405}
406
407status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
408    sp<AMessage> msg = new AMessage(kWhatSetCallback, this);
409    msg->setMessage("callback", callback);
410
411    sp<AMessage> response;
412    return PostAndAwaitResponse(msg, &response);
413}
414
415status_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> &notify) {
416    sp<AMessage> msg = new AMessage(kWhatSetNotification, this);
417    msg->setMessage("on-frame-rendered", notify);
418    return msg->post();
419}
420
421status_t MediaCodec::configure(
422        const sp<AMessage> &format,
423        const sp<Surface> &surface,
424        const sp<ICrypto> &crypto,
425        uint32_t flags) {
426    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
427
428    if (mIsVideo) {
429        format->findInt32("width", &mVideoWidth);
430        format->findInt32("height", &mVideoHeight);
431        if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
432            mRotationDegrees = 0;
433        }
434
435        // Prevent possible integer overflow in downstream code.
436        if (mInitIsEncoder
437                && (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
438            ALOGE("buffer size is too big, width=%d, height=%d", mVideoWidth, mVideoHeight);
439            return BAD_VALUE;
440        }
441    }
442
443    msg->setMessage("format", format);
444    msg->setInt32("flags", flags);
445    msg->setObject("surface", surface);
446
447    if (crypto != NULL) {
448        msg->setPointer("crypto", crypto.get());
449    }
450
451    // save msg for reset
452    mConfigureMsg = msg;
453
454    status_t err;
455    Vector<MediaResource> resources;
456    MediaResource::Type type = (mFlags & kFlagIsSecure) ?
457            MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
458    MediaResource::SubType subtype =
459            mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
460    resources.push_back(MediaResource(type, subtype, 1));
461    // Don't know the buffer size at this point, but it's fine to use 1 because
462    // the reclaimResource call doesn't consider the requester's buffer size for now.
463    resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1));
464    for (int i = 0; i <= kMaxRetry; ++i) {
465        if (i > 0) {
466            // Don't try to reclaim resource for the first time.
467            if (!mResourceManagerService->reclaimResource(resources)) {
468                break;
469            }
470        }
471
472        sp<AMessage> response;
473        err = PostAndAwaitResponse(msg, &response);
474        if (err != OK && err != INVALID_OPERATION) {
475            // MediaCodec now set state to UNINITIALIZED upon any fatal error.
476            // To maintain backward-compatibility, do a reset() to put codec
477            // back into INITIALIZED state.
478            // But don't reset if the err is INVALID_OPERATION, which means
479            // the configure failure is due to wrong state.
480
481            ALOGE("configure failed with err 0x%08x, resetting...", err);
482            reset();
483        }
484        if (!isResourceError(err)) {
485            break;
486        }
487    }
488    return err;
489}
490
491status_t MediaCodec::setInputSurface(
492        const sp<PersistentSurface> &surface) {
493    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
494    msg->setObject("input-surface", surface.get());
495
496    sp<AMessage> response;
497    return PostAndAwaitResponse(msg, &response);
498}
499
500status_t MediaCodec::setSurface(const sp<Surface> &surface) {
501    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
502    msg->setObject("surface", surface);
503
504    sp<AMessage> response;
505    return PostAndAwaitResponse(msg, &response);
506}
507
508status_t MediaCodec::createInputSurface(
509        sp<IGraphicBufferProducer>* bufferProducer) {
510    sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
511
512    sp<AMessage> response;
513    status_t err = PostAndAwaitResponse(msg, &response);
514    if (err == NO_ERROR) {
515        // unwrap the sp<IGraphicBufferProducer>
516        sp<RefBase> obj;
517        bool found = response->findObject("input-surface", &obj);
518        CHECK(found);
519        sp<BufferProducerWrapper> wrapper(
520                static_cast<BufferProducerWrapper*>(obj.get()));
521        *bufferProducer = wrapper->getBufferProducer();
522    } else {
523        ALOGW("createInputSurface failed, err=%d", err);
524    }
525    return err;
526}
527
528uint64_t MediaCodec::getGraphicBufferSize() {
529    if (!mIsVideo) {
530        return 0;
531    }
532
533    uint64_t size = 0;
534    size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]);
535    for (size_t i = 0; i < portNum; ++i) {
536        // TODO: this is just an estimation, we should get the real buffer size from ACodec.
537        size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2;
538    }
539    return size;
540}
541
542void MediaCodec::addResource(
543        MediaResource::Type type, MediaResource::SubType subtype, uint64_t value) {
544    Vector<MediaResource> resources;
545    resources.push_back(MediaResource(type, subtype, value));
546    mResourceManagerService->addResource(
547            getId(mResourceManagerClient), mResourceManagerClient, resources);
548}
549
550status_t MediaCodec::start() {
551    sp<AMessage> msg = new AMessage(kWhatStart, this);
552
553    status_t err;
554    Vector<MediaResource> resources;
555    MediaResource::Type type = (mFlags & kFlagIsSecure) ?
556            MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
557    MediaResource::SubType subtype =
558            mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
559    resources.push_back(MediaResource(type, subtype, 1));
560    // Don't know the buffer size at this point, but it's fine to use 1 because
561    // the reclaimResource call doesn't consider the requester's buffer size for now.
562    resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1));
563    for (int i = 0; i <= kMaxRetry; ++i) {
564        if (i > 0) {
565            // Don't try to reclaim resource for the first time.
566            if (!mResourceManagerService->reclaimResource(resources)) {
567                break;
568            }
569            // Recover codec from previous error before retry start.
570            err = reset();
571            if (err != OK) {
572                ALOGE("retrying start: failed to reset codec");
573                break;
574            }
575            sp<AMessage> response;
576            err = PostAndAwaitResponse(mConfigureMsg, &response);
577            if (err != OK) {
578                ALOGE("retrying start: failed to configure codec");
579                break;
580            }
581        }
582
583        sp<AMessage> response;
584        err = PostAndAwaitResponse(msg, &response);
585        if (!isResourceError(err)) {
586            break;
587        }
588    }
589    return err;
590}
591
592status_t MediaCodec::stop() {
593    sp<AMessage> msg = new AMessage(kWhatStop, this);
594
595    sp<AMessage> response;
596    return PostAndAwaitResponse(msg, &response);
597}
598
599bool MediaCodec::hasPendingBuffer(int portIndex) {
600    const Vector<BufferInfo> &buffers = mPortBuffers[portIndex];
601    for (size_t i = 0; i < buffers.size(); ++i) {
602        const BufferInfo &info = buffers.itemAt(i);
603        if (info.mOwnedByClient) {
604            return true;
605        }
606    }
607    return false;
608}
609
610bool MediaCodec::hasPendingBuffer() {
611    return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput);
612}
613
614status_t MediaCodec::reclaim(bool force) {
615    ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
616    sp<AMessage> msg = new AMessage(kWhatRelease, this);
617    msg->setInt32("reclaimed", 1);
618    msg->setInt32("force", force ? 1 : 0);
619
620    sp<AMessage> response;
621    status_t ret = PostAndAwaitResponse(msg, &response);
622    if (ret == -ENOENT) {
623        ALOGD("MediaCodec looper is gone, skip reclaim");
624        ret = OK;
625    }
626    return ret;
627}
628
629status_t MediaCodec::release() {
630    sp<AMessage> msg = new AMessage(kWhatRelease, this);
631
632    sp<AMessage> response;
633    return PostAndAwaitResponse(msg, &response);
634}
635
636status_t MediaCodec::reset() {
637    /* When external-facing MediaCodec object is created,
638       it is already initialized.  Thus, reset is essentially
639       release() followed by init(), plus clearing the state */
640
641    status_t err = release();
642
643    // unregister handlers
644    if (mCodec != NULL) {
645        if (mCodecLooper != NULL) {
646            mCodecLooper->unregisterHandler(mCodec->id());
647        } else {
648            mLooper->unregisterHandler(mCodec->id());
649        }
650        mCodec = NULL;
651    }
652    mLooper->unregisterHandler(id());
653
654    mFlags = 0;    // clear all flags
655    mStickyError = OK;
656
657    // reset state not reset by setState(UNINITIALIZED)
658    mReplyID = 0;
659    mDequeueInputReplyID = 0;
660    mDequeueOutputReplyID = 0;
661    mDequeueInputTimeoutGeneration = 0;
662    mDequeueOutputTimeoutGeneration = 0;
663    mHaveInputSurface = false;
664
665    if (err == OK) {
666        err = init(mInitName, mInitNameIsType, mInitIsEncoder);
667    }
668    return err;
669}
670
671status_t MediaCodec::queueInputBuffer(
672        size_t index,
673        size_t offset,
674        size_t size,
675        int64_t presentationTimeUs,
676        uint32_t flags,
677        AString *errorDetailMsg) {
678    if (errorDetailMsg != NULL) {
679        errorDetailMsg->clear();
680    }
681
682    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
683    msg->setSize("index", index);
684    msg->setSize("offset", offset);
685    msg->setSize("size", size);
686    msg->setInt64("timeUs", presentationTimeUs);
687    msg->setInt32("flags", flags);
688    msg->setPointer("errorDetailMsg", errorDetailMsg);
689
690    sp<AMessage> response;
691    return PostAndAwaitResponse(msg, &response);
692}
693
694status_t MediaCodec::queueSecureInputBuffer(
695        size_t index,
696        size_t offset,
697        const CryptoPlugin::SubSample *subSamples,
698        size_t numSubSamples,
699        const uint8_t key[16],
700        const uint8_t iv[16],
701        CryptoPlugin::Mode mode,
702        const CryptoPlugin::Pattern &pattern,
703        int64_t presentationTimeUs,
704        uint32_t flags,
705        AString *errorDetailMsg) {
706    if (errorDetailMsg != NULL) {
707        errorDetailMsg->clear();
708    }
709
710    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
711    msg->setSize("index", index);
712    msg->setSize("offset", offset);
713    msg->setPointer("subSamples", (void *)subSamples);
714    msg->setSize("numSubSamples", numSubSamples);
715    msg->setPointer("key", (void *)key);
716    msg->setPointer("iv", (void *)iv);
717    msg->setInt32("mode", mode);
718    msg->setInt32("encryptBlocks", pattern.mEncryptBlocks);
719    msg->setInt32("skipBlocks", pattern.mSkipBlocks);
720    msg->setInt64("timeUs", presentationTimeUs);
721    msg->setInt32("flags", flags);
722    msg->setPointer("errorDetailMsg", errorDetailMsg);
723
724    sp<AMessage> response;
725    status_t err = PostAndAwaitResponse(msg, &response);
726
727    return err;
728}
729
730status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
731    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
732    msg->setInt64("timeoutUs", timeoutUs);
733
734    sp<AMessage> response;
735    status_t err;
736    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
737        return err;
738    }
739
740    CHECK(response->findSize("index", index));
741
742    return OK;
743}
744
745status_t MediaCodec::dequeueOutputBuffer(
746        size_t *index,
747        size_t *offset,
748        size_t *size,
749        int64_t *presentationTimeUs,
750        uint32_t *flags,
751        int64_t timeoutUs) {
752    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this);
753    msg->setInt64("timeoutUs", timeoutUs);
754
755    sp<AMessage> response;
756    status_t err;
757    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
758        return err;
759    }
760
761    CHECK(response->findSize("index", index));
762    CHECK(response->findSize("offset", offset));
763    CHECK(response->findSize("size", size));
764    CHECK(response->findInt64("timeUs", presentationTimeUs));
765    CHECK(response->findInt32("flags", (int32_t *)flags));
766
767    return OK;
768}
769
770status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
771    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
772    msg->setSize("index", index);
773    msg->setInt32("render", true);
774
775    sp<AMessage> response;
776    return PostAndAwaitResponse(msg, &response);
777}
778
779status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
780    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
781    msg->setSize("index", index);
782    msg->setInt32("render", true);
783    msg->setInt64("timestampNs", timestampNs);
784
785    sp<AMessage> response;
786    return PostAndAwaitResponse(msg, &response);
787}
788
789status_t MediaCodec::releaseOutputBuffer(size_t index) {
790    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
791    msg->setSize("index", index);
792
793    sp<AMessage> response;
794    return PostAndAwaitResponse(msg, &response);
795}
796
797status_t MediaCodec::signalEndOfInputStream() {
798    sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this);
799
800    sp<AMessage> response;
801    return PostAndAwaitResponse(msg, &response);
802}
803
804status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
805    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this);
806
807    sp<AMessage> response;
808    status_t err;
809    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
810        return err;
811    }
812
813    CHECK(response->findMessage("format", format));
814
815    return OK;
816}
817
818status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
819    sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this);
820
821    sp<AMessage> response;
822    status_t err;
823    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
824        return err;
825    }
826
827    CHECK(response->findMessage("format", format));
828
829    return OK;
830}
831
832status_t MediaCodec::getName(AString *name) const {
833    sp<AMessage> msg = new AMessage(kWhatGetName, this);
834
835    sp<AMessage> response;
836    status_t err;
837    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
838        return err;
839    }
840
841    CHECK(response->findString("name", name));
842
843    return OK;
844}
845
846status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
847    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
848    msg->setInt32("portIndex", kPortIndexInput);
849    msg->setPointer("buffers", buffers);
850    msg->setInt32("widevine", true);
851
852    sp<AMessage> response;
853    return PostAndAwaitResponse(msg, &response);
854}
855
856status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
857    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
858    msg->setInt32("portIndex", kPortIndexInput);
859    msg->setPointer("buffers", buffers);
860
861    sp<AMessage> response;
862    return PostAndAwaitResponse(msg, &response);
863}
864
865status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
866    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
867    msg->setInt32("portIndex", kPortIndexOutput);
868    msg->setPointer("buffers", buffers);
869
870    sp<AMessage> response;
871    return PostAndAwaitResponse(msg, &response);
872}
873
874status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
875    sp<AMessage> format;
876    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
877}
878
879status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
880    sp<MediaCodecBuffer> buffer;
881    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
882}
883
884status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
885    sp<AMessage> format;
886    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
887}
888
889bool MediaCodec::isExecuting() const {
890    return mState == STARTED || mState == FLUSHED;
891}
892
893status_t MediaCodec::getBufferAndFormat(
894        size_t portIndex, size_t index,
895        sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
896    // use mutex instead of a context switch
897    if (mReleasedByResourceManager) {
898        ALOGE("getBufferAndFormat - resource already released");
899        return DEAD_OBJECT;
900    }
901
902    if (buffer == NULL) {
903        ALOGE("getBufferAndFormat - null MediaCodecBuffer");
904        return INVALID_OPERATION;
905    }
906
907    if (format == NULL) {
908        ALOGE("getBufferAndFormat - null AMessage");
909        return INVALID_OPERATION;
910    }
911
912    buffer->clear();
913    format->clear();
914
915    if (!isExecuting()) {
916        ALOGE("getBufferAndFormat - not executing");
917        return INVALID_OPERATION;
918    }
919
920    // we do not want mPortBuffers to change during this section
921    // we also don't want mOwnedByClient to change during this
922    Mutex::Autolock al(mBufferLock);
923
924    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
925    if (index >= buffers->size()) {
926        ALOGE("getBufferAndFormat - trying to get buffer with "
927              "bad index (index=%zu buffer_size=%zu)", index, buffers->size());
928        return INVALID_OPERATION;
929    }
930
931    const BufferInfo &info = buffers->itemAt(index);
932    if (!info.mOwnedByClient) {
933        ALOGE("getBufferAndFormat - invalid operation "
934              "(the index %zu is not owned by client)", index);
935        return INVALID_OPERATION;
936    }
937
938    *buffer = info.mData;
939    *format = info.mData->format();
940
941    return OK;
942}
943
944status_t MediaCodec::flush() {
945    sp<AMessage> msg = new AMessage(kWhatFlush, this);
946
947    sp<AMessage> response;
948    return PostAndAwaitResponse(msg, &response);
949}
950
951status_t MediaCodec::requestIDRFrame() {
952    (new AMessage(kWhatRequestIDRFrame, this))->post();
953
954    return OK;
955}
956
957void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
958    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
959    msg->setMessage("notify", notify);
960    msg->post();
961}
962
963////////////////////////////////////////////////////////////////////////////////
964
965void MediaCodec::cancelPendingDequeueOperations() {
966    if (mFlags & kFlagDequeueInputPending) {
967        PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
968
969        ++mDequeueInputTimeoutGeneration;
970        mDequeueInputReplyID = 0;
971        mFlags &= ~kFlagDequeueInputPending;
972    }
973
974    if (mFlags & kFlagDequeueOutputPending) {
975        PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
976
977        ++mDequeueOutputTimeoutGeneration;
978        mDequeueOutputReplyID = 0;
979        mFlags &= ~kFlagDequeueOutputPending;
980    }
981}
982
983bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
984    if (!isExecuting() || (mFlags & kFlagIsAsync)
985            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
986        PostReplyWithError(replyID, INVALID_OPERATION);
987        return true;
988    } else if (mFlags & kFlagStickyError) {
989        PostReplyWithError(replyID, getStickyError());
990        return true;
991    }
992
993    ssize_t index = dequeuePortBuffer(kPortIndexInput);
994
995    if (index < 0) {
996        CHECK_EQ(index, -EAGAIN);
997        return false;
998    }
999
1000    sp<AMessage> response = new AMessage;
1001    response->setSize("index", index);
1002    response->postReply(replyID);
1003
1004    return true;
1005}
1006
1007bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
1008    if (!isExecuting() || (mFlags & kFlagIsAsync)
1009            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
1010        PostReplyWithError(replyID, INVALID_OPERATION);
1011    } else if (mFlags & kFlagStickyError) {
1012        PostReplyWithError(replyID, getStickyError());
1013    } else if (mFlags & kFlagOutputBuffersChanged) {
1014        PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
1015        mFlags &= ~kFlagOutputBuffersChanged;
1016    } else if (mFlags & kFlagOutputFormatChanged) {
1017        PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
1018        mFlags &= ~kFlagOutputFormatChanged;
1019    } else {
1020        sp<AMessage> response = new AMessage;
1021        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
1022
1023        if (index < 0) {
1024            CHECK_EQ(index, -EAGAIN);
1025            return false;
1026        }
1027
1028        const sp<MediaCodecBuffer> &buffer =
1029            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
1030
1031        response->setSize("index", index);
1032        response->setSize("offset", buffer->offset());
1033        response->setSize("size", buffer->size());
1034
1035        int64_t timeUs;
1036        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1037
1038        response->setInt64("timeUs", timeUs);
1039
1040        int32_t omxFlags;
1041        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
1042
1043        uint32_t flags = 0;
1044        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
1045            flags |= BUFFER_FLAG_SYNCFRAME;
1046        }
1047        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1048            flags |= BUFFER_FLAG_CODECCONFIG;
1049        }
1050        if (omxFlags & OMX_BUFFERFLAG_EOS) {
1051            flags |= BUFFER_FLAG_EOS;
1052        }
1053
1054        response->setInt32("flags", flags);
1055        response->postReply(replyID);
1056    }
1057
1058    return true;
1059}
1060
1061void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
1062    switch (msg->what()) {
1063        case kWhatCodecNotify:
1064        {
1065            int32_t what;
1066            CHECK(msg->findInt32("what", &what));
1067
1068            switch (what) {
1069                case CodecBase::kWhatError:
1070                {
1071                    int32_t err, actionCode;
1072                    CHECK(msg->findInt32("err", &err));
1073                    CHECK(msg->findInt32("actionCode", &actionCode));
1074
1075                    ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
1076                            err, actionCode, mState);
1077                    if (err == DEAD_OBJECT) {
1078                        mFlags |= kFlagSawMediaServerDie;
1079                        mFlags &= ~kFlagIsComponentAllocated;
1080                    }
1081
1082                    bool sendErrorResponse = true;
1083
1084                    switch (mState) {
1085                        case INITIALIZING:
1086                        {
1087                            setState(UNINITIALIZED);
1088                            break;
1089                        }
1090
1091                        case CONFIGURING:
1092                        {
1093                            setState(actionCode == ACTION_CODE_FATAL ?
1094                                    UNINITIALIZED : INITIALIZED);
1095                            break;
1096                        }
1097
1098                        case STARTING:
1099                        {
1100                            setState(actionCode == ACTION_CODE_FATAL ?
1101                                    UNINITIALIZED : CONFIGURED);
1102                            break;
1103                        }
1104
1105                        case RELEASING:
1106                        {
1107                            // Ignore the error, assuming we'll still get
1108                            // the shutdown complete notification. If we
1109                            // don't, we'll timeout and force release.
1110                            sendErrorResponse = false;
1111                        }
1112                        // fall-thru
1113                        case STOPPING:
1114                        {
1115                            if (mFlags & kFlagSawMediaServerDie) {
1116                                // MediaServer died, there definitely won't
1117                                // be a shutdown complete notification after
1118                                // all.
1119
1120                                // note that we're directly going from
1121                                // STOPPING->UNINITIALIZED, instead of the
1122                                // usual STOPPING->INITIALIZED state.
1123                                setState(UNINITIALIZED);
1124                                if (mState == RELEASING) {
1125                                    mComponentName.clear();
1126                                }
1127                                (new AMessage)->postReply(mReplyID);
1128                                sendErrorResponse = false;
1129                            }
1130                            break;
1131                        }
1132
1133                        case FLUSHING:
1134                        {
1135                            if (actionCode == ACTION_CODE_FATAL) {
1136                                setState(UNINITIALIZED);
1137                            } else {
1138                                setState(
1139                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
1140                            }
1141                            break;
1142                        }
1143
1144                        case FLUSHED:
1145                        case STARTED:
1146                        {
1147                            sendErrorResponse = false;
1148
1149                            setStickyError(err);
1150                            postActivityNotificationIfPossible();
1151
1152                            cancelPendingDequeueOperations();
1153
1154                            if (mFlags & kFlagIsAsync) {
1155                                onError(err, actionCode);
1156                            }
1157                            switch (actionCode) {
1158                            case ACTION_CODE_TRANSIENT:
1159                                break;
1160                            case ACTION_CODE_RECOVERABLE:
1161                                setState(INITIALIZED);
1162                                break;
1163                            default:
1164                                setState(UNINITIALIZED);
1165                                break;
1166                            }
1167                            break;
1168                        }
1169
1170                        default:
1171                        {
1172                            sendErrorResponse = false;
1173
1174                            setStickyError(err);
1175                            postActivityNotificationIfPossible();
1176
1177                            // actionCode in an uninitialized state is always fatal.
1178                            if (mState == UNINITIALIZED) {
1179                                actionCode = ACTION_CODE_FATAL;
1180                            }
1181                            if (mFlags & kFlagIsAsync) {
1182                                onError(err, actionCode);
1183                            }
1184                            switch (actionCode) {
1185                            case ACTION_CODE_TRANSIENT:
1186                                break;
1187                            case ACTION_CODE_RECOVERABLE:
1188                                setState(INITIALIZED);
1189                                break;
1190                            default:
1191                                setState(UNINITIALIZED);
1192                                break;
1193                            }
1194                            break;
1195                        }
1196                    }
1197
1198                    if (sendErrorResponse) {
1199                        PostReplyWithError(mReplyID, err);
1200                    }
1201                    break;
1202                }
1203
1204                case CodecBase::kWhatComponentAllocated:
1205                {
1206                    CHECK_EQ(mState, INITIALIZING);
1207                    setState(INITIALIZED);
1208                    mFlags |= kFlagIsComponentAllocated;
1209
1210                    CHECK(msg->findString("componentName", &mComponentName));
1211
1212                    if (mComponentName.startsWith("OMX.google.")) {
1213                        mFlags |= kFlagUsesSoftwareRenderer;
1214                    } else {
1215                        mFlags &= ~kFlagUsesSoftwareRenderer;
1216                    }
1217
1218                    MediaResource::Type resourceType;
1219                    if (mComponentName.endsWith(".secure")) {
1220                        mFlags |= kFlagIsSecure;
1221                        resourceType = MediaResource::kSecureCodec;
1222                    } else {
1223                        mFlags &= ~kFlagIsSecure;
1224                        resourceType = MediaResource::kNonSecureCodec;
1225                    }
1226
1227                    if (mIsVideo) {
1228                        // audio codec is currently ignored.
1229                        addResource(resourceType, MediaResource::kVideoCodec, 1);
1230                    }
1231
1232                    (new AMessage)->postReply(mReplyID);
1233                    break;
1234                }
1235
1236                case CodecBase::kWhatComponentConfigured:
1237                {
1238                    if (mState == UNINITIALIZED || mState == INITIALIZED) {
1239                        // In case a kWhatError message came in and replied with error,
1240                        // we log a warning and ignore.
1241                        ALOGW("configure interrupted by error, current state %d", mState);
1242                        break;
1243                    }
1244                    CHECK_EQ(mState, CONFIGURING);
1245
1246                    // reset input surface flag
1247                    mHaveInputSurface = false;
1248
1249                    CHECK(msg->findMessage("input-format", &mInputFormat));
1250                    CHECK(msg->findMessage("output-format", &mOutputFormat));
1251                    ALOGV("[%s] configured as input format: %s, output format: %s",
1252                            mComponentName.c_str(),
1253                            mInputFormat->debugString(4).c_str(),
1254                            mOutputFormat->debugString(4).c_str());
1255                    int32_t usingSwRenderer;
1256                    if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
1257                            && usingSwRenderer) {
1258                        mFlags |= kFlagUsesSoftwareRenderer;
1259                    }
1260                    setState(CONFIGURED);
1261                    (new AMessage)->postReply(mReplyID);
1262                    break;
1263                }
1264
1265                case CodecBase::kWhatInputSurfaceCreated:
1266                {
1267                    // response to initiateCreateInputSurface()
1268                    status_t err = NO_ERROR;
1269                    sp<AMessage> response = new AMessage;
1270                    if (!msg->findInt32("err", &err)) {
1271                        sp<RefBase> obj;
1272                        msg->findObject("input-surface", &obj);
1273                        CHECK(msg->findMessage("input-format", &mInputFormat));
1274                        CHECK(msg->findMessage("output-format", &mOutputFormat));
1275                        ALOGV("[%s] input surface created as input format: %s, output format: %s",
1276                                mComponentName.c_str(),
1277                                mInputFormat->debugString(4).c_str(),
1278                                mOutputFormat->debugString(4).c_str());
1279                        CHECK(obj != NULL);
1280                        response->setObject("input-surface", obj);
1281                        mHaveInputSurface = true;
1282                    } else {
1283                        response->setInt32("err", err);
1284                    }
1285                    response->postReply(mReplyID);
1286                    break;
1287                }
1288
1289                case CodecBase::kWhatInputSurfaceAccepted:
1290                {
1291                    // response to initiateSetInputSurface()
1292                    status_t err = NO_ERROR;
1293                    sp<AMessage> response = new AMessage();
1294                    if (!msg->findInt32("err", &err)) {
1295                        CHECK(msg->findMessage("input-format", &mInputFormat));
1296                        CHECK(msg->findMessage("output-format", &mOutputFormat));
1297                        mHaveInputSurface = true;
1298                    } else {
1299                        response->setInt32("err", err);
1300                    }
1301                    response->postReply(mReplyID);
1302                    break;
1303                }
1304
1305                case CodecBase::kWhatSignaledInputEOS:
1306                {
1307                    // response to signalEndOfInputStream()
1308                    sp<AMessage> response = new AMessage;
1309                    status_t err;
1310                    if (msg->findInt32("err", &err)) {
1311                        response->setInt32("err", err);
1312                    }
1313                    response->postReply(mReplyID);
1314                    break;
1315                }
1316
1317
1318                case CodecBase::kWhatBuffersAllocated:
1319                {
1320                    Mutex::Autolock al(mBufferLock);
1321                    int32_t portIndex;
1322                    CHECK(msg->findInt32("portIndex", &portIndex));
1323
1324                    ALOGV("%s buffers allocated",
1325                          portIndex == kPortIndexInput ? "input" : "output");
1326
1327                    CHECK(portIndex == kPortIndexInput
1328                            || portIndex == kPortIndexOutput);
1329
1330                    mPortBuffers[portIndex].clear();
1331                    mPortBufferArrays[portIndex].clear();
1332
1333                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1334
1335                    sp<RefBase> obj;
1336                    CHECK(msg->findObject("portDesc", &obj));
1337
1338                    sp<CodecBase::PortDescription> portDesc =
1339                        static_cast<CodecBase::PortDescription *>(obj.get());
1340
1341                    size_t numBuffers = portDesc->countBuffers();
1342
1343                    size_t totalSize = 0;
1344                    for (size_t i = 0; i < numBuffers; ++i) {
1345                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1346                            totalSize += portDesc->bufferAt(i)->capacity();
1347                        }
1348                    }
1349
1350                    if (totalSize) {
1351                        mDealer = new MemoryDealer(totalSize, "MediaCodec");
1352                    }
1353
1354                    for (size_t i = 0; i < numBuffers; ++i) {
1355                        BufferInfo info;
1356                        info.mBufferID = portDesc->bufferIDAt(i);
1357                        info.mOwnedByClient = false;
1358                        sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i);
1359                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1360                            info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity());
1361                            buffer = new SharedMemoryBuffer(
1362                                    mInputFormat, info.mSharedEncryptedBuffer);
1363                        }
1364                        buffers->push_back(info);
1365                        mPortBufferArrays[portIndex].push_back(buffer);
1366                    }
1367
1368                    if (portIndex == kPortIndexOutput) {
1369                        if (mState == STARTING) {
1370                            // We're always allocating output buffers after
1371                            // allocating input buffers, so this is a good
1372                            // indication that now all buffers are allocated.
1373                            if (mIsVideo) {
1374                                addResource(
1375                                        MediaResource::kGraphicMemory,
1376                                        MediaResource::kUnspecifiedSubType,
1377                                        getGraphicBufferSize());
1378                            }
1379                            setState(STARTED);
1380                            (new AMessage)->postReply(mReplyID);
1381                        } else {
1382                            mFlags |= kFlagOutputBuffersChanged;
1383                            postActivityNotificationIfPossible();
1384                        }
1385                    }
1386                    break;
1387                }
1388
1389                case CodecBase::kWhatOutputFramesRendered:
1390                {
1391                    // ignore these in all states except running, and check that we have a
1392                    // notification set
1393                    if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1394                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1395                        notify->setMessage("data", msg);
1396                        notify->post();
1397                    }
1398                    break;
1399                }
1400
1401                case CodecBase::kWhatFillThisBuffer:
1402                {
1403                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1404
1405                    if (mState == FLUSHING
1406                            || mState == STOPPING
1407                            || mState == RELEASING) {
1408                        returnBuffersToCodecOnPort(kPortIndexInput);
1409                        break;
1410                    }
1411
1412                    // TODO: hold reference of buffer from downstream when
1413                    // mPortBuffers is removed.
1414
1415                    if (!mCSD.empty()) {
1416                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1417                        CHECK_GE(index, 0);
1418
1419                        // If codec specific data had been specified as
1420                        // part of the format in the call to configure and
1421                        // if there's more csd left, we submit it here
1422                        // clients only get access to input buffers once
1423                        // this data has been exhausted.
1424
1425                        status_t err = queueCSDInputBuffer(index);
1426
1427                        if (err != OK) {
1428                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1429                                  err);
1430
1431                            setStickyError(err);
1432                            postActivityNotificationIfPossible();
1433
1434                            cancelPendingDequeueOperations();
1435                        }
1436                        break;
1437                    }
1438
1439                    if (mFlags & kFlagIsAsync) {
1440                        if (!mHaveInputSurface) {
1441                            if (mState == FLUSHED) {
1442                                mHavePendingInputBuffers = true;
1443                            } else {
1444                                onInputBufferAvailable();
1445                            }
1446                        }
1447                    } else if (mFlags & kFlagDequeueInputPending) {
1448                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1449
1450                        ++mDequeueInputTimeoutGeneration;
1451                        mFlags &= ~kFlagDequeueInputPending;
1452                        mDequeueInputReplyID = 0;
1453                    } else {
1454                        postActivityNotificationIfPossible();
1455                    }
1456                    break;
1457                }
1458
1459                case CodecBase::kWhatDrainThisBuffer:
1460                {
1461                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1462
1463                    if (mState == FLUSHING
1464                            || mState == STOPPING
1465                            || mState == RELEASING) {
1466                        returnBuffersToCodecOnPort(kPortIndexOutput);
1467                        break;
1468                    }
1469
1470                    sp<RefBase> obj;
1471                    CHECK(msg->findObject("buffer", &obj));
1472                    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
1473                    // TODO: hold buffer's reference when we remove mPortBuffers
1474
1475                    int32_t omxFlags;
1476                    CHECK(msg->findInt32("flags", &omxFlags));
1477
1478                    buffer->meta()->setInt32("omxFlags", omxFlags);
1479                    if (mOutputFormat != buffer->format()) {
1480                        mOutputFormat = buffer->format();
1481                        ALOGV("[%s] output format changed to: %s",
1482                                mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
1483
1484                        if (mSoftRenderer == NULL &&
1485                                mSurface != NULL &&
1486                                (mFlags & kFlagUsesSoftwareRenderer)) {
1487                            AString mime;
1488                            CHECK(mOutputFormat->findString("mime", &mime));
1489
1490                            // TODO: propagate color aspects to software renderer to allow better
1491                            // color conversion to RGB. For now, just mark dataspace for YUV
1492                            // rendering.
1493                            int32_t dataSpace;
1494                            if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
1495                                ALOGD("[%s] setting dataspace on output surface to #%x",
1496                                        mComponentName.c_str(), dataSpace);
1497                                int err = native_window_set_buffers_data_space(
1498                                        mSurface.get(), (android_dataspace)dataSpace);
1499                                ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
1500                            }
1501
1502                            if (mime.startsWithIgnoreCase("video/")) {
1503                                mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1504                            }
1505                        }
1506
1507                        if (mFlags & kFlagIsEncoder) {
1508                            // Before we announce the format change we should
1509                            // collect codec specific data and amend the output
1510                            // format as necessary.
1511                            if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1512                                status_t err =
1513                                    amendOutputFormatWithCodecSpecificData(buffer);
1514
1515                                if (err != OK) {
1516                                    ALOGE("Codec spit out malformed codec "
1517                                          "specific data!");
1518                                }
1519                            }
1520                        }
1521
1522                        if (mFlags & kFlagIsAsync) {
1523                            onOutputFormatChanged();
1524                        } else {
1525                            mFlags |= kFlagOutputFormatChanged;
1526                            postActivityNotificationIfPossible();
1527                        }
1528
1529                        // Notify mCrypto of video resolution changes
1530                        if (mCrypto != NULL) {
1531                            int32_t left, top, right, bottom, width, height;
1532                            if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1533                                mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1534                            } else if (mOutputFormat->findInt32("width", &width)
1535                                    && mOutputFormat->findInt32("height", &height)) {
1536                                mCrypto->notifyResolution(width, height);
1537                            }
1538                        }
1539                    }
1540
1541                    if (mFlags & kFlagIsAsync) {
1542                        onOutputBufferAvailable();
1543                    } else if (mFlags & kFlagDequeueOutputPending) {
1544                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1545
1546                        ++mDequeueOutputTimeoutGeneration;
1547                        mFlags &= ~kFlagDequeueOutputPending;
1548                        mDequeueOutputReplyID = 0;
1549                    } else {
1550                        postActivityNotificationIfPossible();
1551                    }
1552
1553                    break;
1554                }
1555
1556                case CodecBase::kWhatEOS:
1557                {
1558                    // We already notify the client of this by using the
1559                    // corresponding flag in "onOutputBufferReady".
1560                    break;
1561                }
1562
1563                case CodecBase::kWhatStopCompleted:
1564                {
1565                    if (mState != STOPPING) {
1566                        ALOGW("Received kWhatStopCompleted in state %d", mState);
1567                        break;
1568                    }
1569                    setState(INITIALIZED);
1570                    (new AMessage)->postReply(mReplyID);
1571                    break;
1572                }
1573
1574                case CodecBase::kWhatReleaseCompleted:
1575                {
1576                    if (mState != RELEASING) {
1577                        ALOGW("Received kWhatReleaseCompleted in state %d", mState);
1578                        break;
1579                    }
1580                    setState(UNINITIALIZED);
1581                    mComponentName.clear();
1582
1583                    mFlags &= ~kFlagIsComponentAllocated;
1584
1585                    mResourceManagerService->removeResource(getId(mResourceManagerClient));
1586
1587                    (new AMessage)->postReply(mReplyID);
1588                    break;
1589                }
1590
1591                case CodecBase::kWhatFlushCompleted:
1592                {
1593                    if (mState != FLUSHING) {
1594                        ALOGW("received FlushCompleted message in state %d",
1595                                mState);
1596                        break;
1597                    }
1598
1599                    if (mFlags & kFlagIsAsync) {
1600                        setState(FLUSHED);
1601                    } else {
1602                        setState(STARTED);
1603                        mCodec->signalResume();
1604                    }
1605
1606                    (new AMessage)->postReply(mReplyID);
1607                    break;
1608                }
1609
1610                default:
1611                    TRESPASS();
1612            }
1613            break;
1614        }
1615
1616        case kWhatInit:
1617        {
1618            sp<AReplyToken> replyID;
1619            CHECK(msg->senderAwaitsResponse(&replyID));
1620
1621            if (mState != UNINITIALIZED) {
1622                PostReplyWithError(replyID, INVALID_OPERATION);
1623                break;
1624            }
1625
1626            mReplyID = replyID;
1627            setState(INITIALIZING);
1628
1629            AString name;
1630            CHECK(msg->findString("name", &name));
1631
1632            int32_t nameIsType;
1633            int32_t encoder = false;
1634            CHECK(msg->findInt32("nameIsType", &nameIsType));
1635            if (nameIsType) {
1636                CHECK(msg->findInt32("encoder", &encoder));
1637            }
1638
1639            sp<AMessage> format = new AMessage;
1640
1641            if (nameIsType) {
1642                format->setString("mime", name.c_str());
1643                format->setInt32("encoder", encoder);
1644            } else {
1645                format->setString("componentName", name.c_str());
1646            }
1647
1648            mCodec->initiateAllocateComponent(format);
1649            break;
1650        }
1651
1652        case kWhatSetNotification:
1653        {
1654            sp<AMessage> notify;
1655            if (msg->findMessage("on-frame-rendered", &notify)) {
1656                mOnFrameRenderedNotification = notify;
1657            }
1658            break;
1659        }
1660
1661        case kWhatSetCallback:
1662        {
1663            sp<AReplyToken> replyID;
1664            CHECK(msg->senderAwaitsResponse(&replyID));
1665
1666            if (mState == UNINITIALIZED
1667                    || mState == INITIALIZING
1668                    || isExecuting()) {
1669                // callback can't be set after codec is executing,
1670                // or before it's initialized (as the callback
1671                // will be cleared when it goes to INITIALIZED)
1672                PostReplyWithError(replyID, INVALID_OPERATION);
1673                break;
1674            }
1675
1676            sp<AMessage> callback;
1677            CHECK(msg->findMessage("callback", &callback));
1678
1679            mCallback = callback;
1680
1681            if (mCallback != NULL) {
1682                ALOGI("MediaCodec will operate in async mode");
1683                mFlags |= kFlagIsAsync;
1684            } else {
1685                mFlags &= ~kFlagIsAsync;
1686            }
1687
1688            sp<AMessage> response = new AMessage;
1689            response->postReply(replyID);
1690            break;
1691        }
1692
1693        case kWhatConfigure:
1694        {
1695            sp<AReplyToken> replyID;
1696            CHECK(msg->senderAwaitsResponse(&replyID));
1697
1698            if (mState != INITIALIZED) {
1699                PostReplyWithError(replyID, INVALID_OPERATION);
1700                break;
1701            }
1702
1703            sp<RefBase> obj;
1704            CHECK(msg->findObject("surface", &obj));
1705
1706            sp<AMessage> format;
1707            CHECK(msg->findMessage("format", &format));
1708
1709            int32_t push;
1710            if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
1711                mFlags |= kFlagPushBlankBuffersOnShutdown;
1712            }
1713
1714            if (obj != NULL) {
1715                format->setObject("native-window", obj);
1716                status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
1717                if (err != OK) {
1718                    PostReplyWithError(replyID, err);
1719                    break;
1720                }
1721            } else {
1722                handleSetSurface(NULL);
1723            }
1724
1725            mReplyID = replyID;
1726            setState(CONFIGURING);
1727
1728            void *crypto;
1729            if (!msg->findPointer("crypto", &crypto)) {
1730                crypto = NULL;
1731            }
1732
1733            mCrypto = static_cast<ICrypto *>(crypto);
1734
1735            uint32_t flags;
1736            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1737
1738            if (flags & CONFIGURE_FLAG_ENCODE) {
1739                format->setInt32("encoder", true);
1740                mFlags |= kFlagIsEncoder;
1741            }
1742
1743            extractCSD(format);
1744
1745            mCodec->initiateConfigureComponent(format);
1746            break;
1747        }
1748
1749        case kWhatSetSurface:
1750        {
1751            sp<AReplyToken> replyID;
1752            CHECK(msg->senderAwaitsResponse(&replyID));
1753
1754            status_t err = OK;
1755            sp<Surface> surface;
1756
1757            switch (mState) {
1758                case CONFIGURED:
1759                case STARTED:
1760                case FLUSHED:
1761                {
1762                    sp<RefBase> obj;
1763                    (void)msg->findObject("surface", &obj);
1764                    sp<Surface> surface = static_cast<Surface *>(obj.get());
1765                    if (mSurface == NULL) {
1766                        // do not support setting surface if it was not set
1767                        err = INVALID_OPERATION;
1768                    } else if (obj == NULL) {
1769                        // do not support unsetting surface
1770                        err = BAD_VALUE;
1771                    } else {
1772                        err = connectToSurface(surface);
1773                        if (err == ALREADY_EXISTS) {
1774                            // reconnecting to same surface
1775                            err = OK;
1776                        } else {
1777                            if (err == OK) {
1778                                if (mFlags & kFlagUsesSoftwareRenderer) {
1779                                    if (mSoftRenderer != NULL
1780                                            && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1781                                        pushBlankBuffersToNativeWindow(mSurface.get());
1782                                    }
1783                                    mSoftRenderer = new SoftwareRenderer(surface);
1784                                    // TODO: check if this was successful
1785                                } else {
1786                                    err = mCodec->setSurface(surface);
1787                                }
1788                            }
1789                            if (err == OK) {
1790                                (void)disconnectFromSurface();
1791                                mSurface = surface;
1792                            }
1793                        }
1794                    }
1795                    break;
1796                }
1797
1798                default:
1799                    err = INVALID_OPERATION;
1800                    break;
1801            }
1802
1803            PostReplyWithError(replyID, err);
1804            break;
1805        }
1806
1807        case kWhatCreateInputSurface:
1808        case kWhatSetInputSurface:
1809        {
1810            sp<AReplyToken> replyID;
1811            CHECK(msg->senderAwaitsResponse(&replyID));
1812
1813            // Must be configured, but can't have been started yet.
1814            if (mState != CONFIGURED) {
1815                PostReplyWithError(replyID, INVALID_OPERATION);
1816                break;
1817            }
1818
1819            mReplyID = replyID;
1820            if (msg->what() == kWhatCreateInputSurface) {
1821                mCodec->initiateCreateInputSurface();
1822            } else {
1823                sp<RefBase> obj;
1824                CHECK(msg->findObject("input-surface", &obj));
1825
1826                mCodec->initiateSetInputSurface(
1827                        static_cast<PersistentSurface *>(obj.get()));
1828            }
1829            break;
1830        }
1831        case kWhatStart:
1832        {
1833            sp<AReplyToken> replyID;
1834            CHECK(msg->senderAwaitsResponse(&replyID));
1835
1836            if (mState == FLUSHED) {
1837                setState(STARTED);
1838                if (mHavePendingInputBuffers) {
1839                    onInputBufferAvailable();
1840                    mHavePendingInputBuffers = false;
1841                }
1842                mCodec->signalResume();
1843                PostReplyWithError(replyID, OK);
1844                break;
1845            } else if (mState != CONFIGURED) {
1846                PostReplyWithError(replyID, INVALID_OPERATION);
1847                break;
1848            }
1849
1850            mReplyID = replyID;
1851            setState(STARTING);
1852
1853            mCodec->initiateStart();
1854            break;
1855        }
1856
1857        case kWhatStop:
1858        case kWhatRelease:
1859        {
1860            State targetState =
1861                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1862
1863            sp<AReplyToken> replyID;
1864            CHECK(msg->senderAwaitsResponse(&replyID));
1865
1866            // already stopped/released
1867            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
1868                sp<AMessage> response = new AMessage;
1869                response->setInt32("err", OK);
1870                response->postReply(replyID);
1871                break;
1872            }
1873
1874            int32_t reclaimed = 0;
1875            msg->findInt32("reclaimed", &reclaimed);
1876            if (reclaimed) {
1877                mReleasedByResourceManager = true;
1878
1879                int32_t force = 0;
1880                msg->findInt32("force", &force);
1881                if (!force && hasPendingBuffer()) {
1882                    ALOGW("Can't reclaim codec right now due to pending buffers.");
1883
1884                    // return WOULD_BLOCK to ask resource manager to retry later.
1885                    sp<AMessage> response = new AMessage;
1886                    response->setInt32("err", WOULD_BLOCK);
1887                    response->postReply(replyID);
1888
1889                    // notify the async client
1890                    if (mFlags & kFlagIsAsync) {
1891                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
1892                    }
1893                    break;
1894                }
1895            }
1896
1897            bool isReleasingAllocatedComponent =
1898                    (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
1899            if (!isReleasingAllocatedComponent // See 1
1900                    && mState != INITIALIZED
1901                    && mState != CONFIGURED && !isExecuting()) {
1902                // 1) Permit release to shut down the component if allocated.
1903                //
1904                // 2) We may be in "UNINITIALIZED" state already and
1905                // also shutdown the encoder/decoder without the
1906                // client being aware of this if media server died while
1907                // we were being stopped. The client would assume that
1908                // after stop() returned, it would be safe to call release()
1909                // and it should be in this case, no harm to allow a release()
1910                // if we're already uninitialized.
1911                sp<AMessage> response = new AMessage;
1912                // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
1913                // the previous stop/release completes and then reply with OK.
1914                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1915                response->setInt32("err", err);
1916                if (err == OK && targetState == UNINITIALIZED) {
1917                    mComponentName.clear();
1918                }
1919                response->postReply(replyID);
1920                break;
1921            }
1922
1923            // If we're flushing, or we're stopping but received a release
1924            // request, post the reply for the pending call first, and consider
1925            // it done. The reply token will be replaced after this, and we'll
1926            // no longer be able to reply.
1927            if (mState == FLUSHING || mState == STOPPING) {
1928                (new AMessage)->postReply(mReplyID);
1929            }
1930
1931            if (mFlags & kFlagSawMediaServerDie) {
1932                // It's dead, Jim. Don't expect initiateShutdown to yield
1933                // any useful results now...
1934                setState(UNINITIALIZED);
1935                if (targetState == UNINITIALIZED) {
1936                    mComponentName.clear();
1937                }
1938                (new AMessage)->postReply(replyID);
1939                break;
1940            }
1941
1942            // If we already have an error, component may not be able to
1943            // complete the shutdown properly. If we're stopping, post the
1944            // reply now with an error to unblock the client, client can
1945            // release after the failure (instead of ANR).
1946            if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
1947                PostReplyWithError(replyID, getStickyError());
1948                break;
1949            }
1950
1951            mReplyID = replyID;
1952            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1953
1954            mCodec->initiateShutdown(
1955                    msg->what() == kWhatStop /* keepComponentAllocated */);
1956
1957            returnBuffersToCodec(reclaimed);
1958
1959            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1960                pushBlankBuffersToNativeWindow(mSurface.get());
1961            }
1962
1963            break;
1964        }
1965
1966        case kWhatDequeueInputBuffer:
1967        {
1968            sp<AReplyToken> replyID;
1969            CHECK(msg->senderAwaitsResponse(&replyID));
1970
1971            if (mFlags & kFlagIsAsync) {
1972                ALOGE("dequeueOutputBuffer can't be used in async mode");
1973                PostReplyWithError(replyID, INVALID_OPERATION);
1974                break;
1975            }
1976
1977            if (mHaveInputSurface) {
1978                ALOGE("dequeueInputBuffer can't be used with input surface");
1979                PostReplyWithError(replyID, INVALID_OPERATION);
1980                break;
1981            }
1982
1983            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1984                break;
1985            }
1986
1987            int64_t timeoutUs;
1988            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1989
1990            if (timeoutUs == 0ll) {
1991                PostReplyWithError(replyID, -EAGAIN);
1992                break;
1993            }
1994
1995            mFlags |= kFlagDequeueInputPending;
1996            mDequeueInputReplyID = replyID;
1997
1998            if (timeoutUs > 0ll) {
1999                sp<AMessage> timeoutMsg =
2000                    new AMessage(kWhatDequeueInputTimedOut, this);
2001                timeoutMsg->setInt32(
2002                        "generation", ++mDequeueInputTimeoutGeneration);
2003                timeoutMsg->post(timeoutUs);
2004            }
2005            break;
2006        }
2007
2008        case kWhatDequeueInputTimedOut:
2009        {
2010            int32_t generation;
2011            CHECK(msg->findInt32("generation", &generation));
2012
2013            if (generation != mDequeueInputTimeoutGeneration) {
2014                // Obsolete
2015                break;
2016            }
2017
2018            CHECK(mFlags & kFlagDequeueInputPending);
2019
2020            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
2021
2022            mFlags &= ~kFlagDequeueInputPending;
2023            mDequeueInputReplyID = 0;
2024            break;
2025        }
2026
2027        case kWhatQueueInputBuffer:
2028        {
2029            sp<AReplyToken> replyID;
2030            CHECK(msg->senderAwaitsResponse(&replyID));
2031
2032            if (!isExecuting()) {
2033                PostReplyWithError(replyID, INVALID_OPERATION);
2034                break;
2035            } else if (mFlags & kFlagStickyError) {
2036                PostReplyWithError(replyID, getStickyError());
2037                break;
2038            }
2039
2040            status_t err = onQueueInputBuffer(msg);
2041
2042            PostReplyWithError(replyID, err);
2043            break;
2044        }
2045
2046        case kWhatDequeueOutputBuffer:
2047        {
2048            sp<AReplyToken> replyID;
2049            CHECK(msg->senderAwaitsResponse(&replyID));
2050
2051            if (mFlags & kFlagIsAsync) {
2052                ALOGE("dequeueOutputBuffer can't be used in async mode");
2053                PostReplyWithError(replyID, INVALID_OPERATION);
2054                break;
2055            }
2056
2057            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
2058                break;
2059            }
2060
2061            int64_t timeoutUs;
2062            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2063
2064            if (timeoutUs == 0ll) {
2065                PostReplyWithError(replyID, -EAGAIN);
2066                break;
2067            }
2068
2069            mFlags |= kFlagDequeueOutputPending;
2070            mDequeueOutputReplyID = replyID;
2071
2072            if (timeoutUs > 0ll) {
2073                sp<AMessage> timeoutMsg =
2074                    new AMessage(kWhatDequeueOutputTimedOut, this);
2075                timeoutMsg->setInt32(
2076                        "generation", ++mDequeueOutputTimeoutGeneration);
2077                timeoutMsg->post(timeoutUs);
2078            }
2079            break;
2080        }
2081
2082        case kWhatDequeueOutputTimedOut:
2083        {
2084            int32_t generation;
2085            CHECK(msg->findInt32("generation", &generation));
2086
2087            if (generation != mDequeueOutputTimeoutGeneration) {
2088                // Obsolete
2089                break;
2090            }
2091
2092            CHECK(mFlags & kFlagDequeueOutputPending);
2093
2094            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2095
2096            mFlags &= ~kFlagDequeueOutputPending;
2097            mDequeueOutputReplyID = 0;
2098            break;
2099        }
2100
2101        case kWhatReleaseOutputBuffer:
2102        {
2103            sp<AReplyToken> replyID;
2104            CHECK(msg->senderAwaitsResponse(&replyID));
2105
2106            if (!isExecuting()) {
2107                PostReplyWithError(replyID, INVALID_OPERATION);
2108                break;
2109            } else if (mFlags & kFlagStickyError) {
2110                PostReplyWithError(replyID, getStickyError());
2111                break;
2112            }
2113
2114            status_t err = onReleaseOutputBuffer(msg);
2115
2116            PostReplyWithError(replyID, err);
2117            break;
2118        }
2119
2120        case kWhatSignalEndOfInputStream:
2121        {
2122            sp<AReplyToken> replyID;
2123            CHECK(msg->senderAwaitsResponse(&replyID));
2124
2125            if (!isExecuting() || !mHaveInputSurface) {
2126                PostReplyWithError(replyID, INVALID_OPERATION);
2127                break;
2128            } else if (mFlags & kFlagStickyError) {
2129                PostReplyWithError(replyID, getStickyError());
2130                break;
2131            }
2132
2133            mReplyID = replyID;
2134            mCodec->signalEndOfInputStream();
2135            break;
2136        }
2137
2138        case kWhatGetBuffers:
2139        {
2140            sp<AReplyToken> replyID;
2141            CHECK(msg->senderAwaitsResponse(&replyID));
2142            // Unfortunately widevine legacy source requires knowing all of the
2143            // codec input buffers, so we have to provide them even in async mode.
2144            int32_t widevine = 0;
2145            msg->findInt32("widevine", &widevine);
2146
2147            if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
2148                PostReplyWithError(replyID, INVALID_OPERATION);
2149                break;
2150            } else if (mFlags & kFlagStickyError) {
2151                PostReplyWithError(replyID, getStickyError());
2152                break;
2153            }
2154
2155            int32_t portIndex;
2156            CHECK(msg->findInt32("portIndex", &portIndex));
2157
2158            Vector<sp<MediaCodecBuffer> > *dstBuffers;
2159            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2160
2161            dstBuffers->clear();
2162            // If we're using input surface (either non-persistent created by
2163            // createInputSurface(), or persistent set by setInputSurface()),
2164            // give the client an empty input buffers array.
2165            if (portIndex != kPortIndexInput || !mHaveInputSurface) {
2166                const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex];
2167
2168                for (size_t i = 0; i < srcBuffers.size(); ++i) {
2169                    dstBuffers->push_back(srcBuffers[i]);
2170                }
2171            }
2172
2173            (new AMessage)->postReply(replyID);
2174            break;
2175        }
2176
2177        case kWhatFlush:
2178        {
2179            sp<AReplyToken> replyID;
2180            CHECK(msg->senderAwaitsResponse(&replyID));
2181
2182            if (!isExecuting()) {
2183                PostReplyWithError(replyID, INVALID_OPERATION);
2184                break;
2185            } else if (mFlags & kFlagStickyError) {
2186                PostReplyWithError(replyID, getStickyError());
2187                break;
2188            }
2189
2190            mReplyID = replyID;
2191            // TODO: skip flushing if already FLUSHED
2192            setState(FLUSHING);
2193
2194            mCodec->signalFlush();
2195            returnBuffersToCodec();
2196            break;
2197        }
2198
2199        case kWhatGetInputFormat:
2200        case kWhatGetOutputFormat:
2201        {
2202            sp<AMessage> format =
2203                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2204
2205            sp<AReplyToken> replyID;
2206            CHECK(msg->senderAwaitsResponse(&replyID));
2207
2208            if ((mState != CONFIGURED && mState != STARTING &&
2209                 mState != STARTED && mState != FLUSHING &&
2210                 mState != FLUSHED)
2211                    || format == NULL) {
2212                PostReplyWithError(replyID, INVALID_OPERATION);
2213                break;
2214            } else if (mFlags & kFlagStickyError) {
2215                PostReplyWithError(replyID, getStickyError());
2216                break;
2217            }
2218
2219            sp<AMessage> response = new AMessage;
2220            response->setMessage("format", format);
2221            response->postReply(replyID);
2222            break;
2223        }
2224
2225        case kWhatRequestIDRFrame:
2226        {
2227            mCodec->signalRequestIDRFrame();
2228            break;
2229        }
2230
2231        case kWhatRequestActivityNotification:
2232        {
2233            CHECK(mActivityNotify == NULL);
2234            CHECK(msg->findMessage("notify", &mActivityNotify));
2235
2236            postActivityNotificationIfPossible();
2237            break;
2238        }
2239
2240        case kWhatGetName:
2241        {
2242            sp<AReplyToken> replyID;
2243            CHECK(msg->senderAwaitsResponse(&replyID));
2244
2245            if (mComponentName.empty()) {
2246                PostReplyWithError(replyID, INVALID_OPERATION);
2247                break;
2248            }
2249
2250            sp<AMessage> response = new AMessage;
2251            response->setString("name", mComponentName.c_str());
2252            response->postReply(replyID);
2253            break;
2254        }
2255
2256        case kWhatSetParameters:
2257        {
2258            sp<AReplyToken> replyID;
2259            CHECK(msg->senderAwaitsResponse(&replyID));
2260
2261            sp<AMessage> params;
2262            CHECK(msg->findMessage("params", &params));
2263
2264            status_t err = onSetParameters(params);
2265
2266            PostReplyWithError(replyID, err);
2267            break;
2268        }
2269
2270        default:
2271            TRESPASS();
2272    }
2273}
2274
2275void MediaCodec::extractCSD(const sp<AMessage> &format) {
2276    mCSD.clear();
2277
2278    size_t i = 0;
2279    for (;;) {
2280        sp<ABuffer> csd;
2281        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2282            break;
2283        }
2284        if (csd->size() == 0) {
2285            ALOGW("csd-%zu size is 0", i);
2286        }
2287
2288        mCSD.push_back(csd);
2289        ++i;
2290    }
2291
2292    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2293}
2294
2295status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2296    CHECK(!mCSD.empty());
2297
2298    const BufferInfo *info =
2299        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2300
2301    sp<ABuffer> csd = *mCSD.begin();
2302    mCSD.erase(mCSD.begin());
2303
2304    const sp<MediaCodecBuffer> &codecInputData = info->mData;
2305
2306    if (csd->size() > codecInputData->capacity()) {
2307        return -EINVAL;
2308    }
2309
2310    memcpy(codecInputData->data(), csd->data(), csd->size());
2311
2312    AString errorDetailMsg;
2313
2314    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2315    msg->setSize("index", bufferIndex);
2316    msg->setSize("offset", 0);
2317    msg->setSize("size", csd->size());
2318    msg->setInt64("timeUs", 0ll);
2319    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2320    msg->setPointer("errorDetailMsg", &errorDetailMsg);
2321
2322    return onQueueInputBuffer(msg);
2323}
2324
2325void MediaCodec::setState(State newState) {
2326    if (newState == INITIALIZED || newState == UNINITIALIZED) {
2327        delete mSoftRenderer;
2328        mSoftRenderer = NULL;
2329
2330        mCrypto.clear();
2331        handleSetSurface(NULL);
2332
2333        mInputFormat.clear();
2334        mOutputFormat.clear();
2335        mFlags &= ~kFlagOutputFormatChanged;
2336        mFlags &= ~kFlagOutputBuffersChanged;
2337        mFlags &= ~kFlagStickyError;
2338        mFlags &= ~kFlagIsEncoder;
2339        mFlags &= ~kFlagIsAsync;
2340        mStickyError = OK;
2341
2342        mActivityNotify.clear();
2343        mCallback.clear();
2344    }
2345
2346    if (newState == UNINITIALIZED) {
2347        // return any straggling buffers, e.g. if we got here on an error
2348        returnBuffersToCodec();
2349
2350        // The component is gone, mediaserver's probably back up already
2351        // but should definitely be back up should we try to instantiate
2352        // another component.. and the cycle continues.
2353        mFlags &= ~kFlagSawMediaServerDie;
2354    }
2355
2356    mState = newState;
2357
2358    cancelPendingDequeueOperations();
2359
2360    updateBatteryStat();
2361}
2362
2363void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2364    returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2365    returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2366}
2367
2368void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2369    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2370    Mutex::Autolock al(mBufferLock);
2371
2372    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2373
2374    for (size_t i = 0; i < buffers->size(); ++i) {
2375        BufferInfo *info = &buffers->editItemAt(i);
2376
2377        if (info->mNotify != NULL) {
2378            sp<AMessage> msg = info->mNotify;
2379            info->mNotify = NULL;
2380            msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL)
2381                    ? info->mSecureData : info->mData);
2382            if (isReclaim && info->mOwnedByClient) {
2383                ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2384                        portIndex, i);
2385            } else {
2386                info->mOwnedByClient = false;
2387                info->mData.clear();
2388                info->mSecureData.clear();
2389            }
2390
2391            if (portIndex == kPortIndexInput) {
2392                /* no error, just returning buffers */
2393                msg->setInt32("err", OK);
2394            }
2395            msg->post();
2396        }
2397    }
2398
2399    mAvailPortBuffers[portIndex].clear();
2400}
2401
2402size_t MediaCodec::updateBuffers(
2403        int32_t portIndex, const sp<AMessage> &msg) {
2404    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2405
2406    uint32_t bufferID;
2407    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2408    sp<RefBase> obj;
2409    CHECK(msg->findObject("buffer", &obj));
2410    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
2411
2412    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2413
2414    for (size_t i = 0; i < buffers->size(); ++i) {
2415        BufferInfo *info = &buffers->editItemAt(i);
2416
2417        if (info->mBufferID == bufferID) {
2418            CHECK(info->mNotify == NULL);
2419            CHECK(msg->findMessage("reply", &info->mNotify));
2420
2421            if (portIndex == kPortIndexInput && mCrypto != NULL) {
2422                info->mSecureData = buffer;
2423                info->mData = mPortBufferArrays[portIndex][i];
2424            } else {
2425                info->mData = buffer;
2426            }
2427            mAvailPortBuffers[portIndex].push_back(i);
2428
2429            return i;
2430        }
2431    }
2432
2433    TRESPASS();
2434
2435    return 0;
2436}
2437
2438status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2439    size_t index;
2440    size_t offset;
2441    size_t size;
2442    int64_t timeUs;
2443    uint32_t flags;
2444    CHECK(msg->findSize("index", &index));
2445    CHECK(msg->findSize("offset", &offset));
2446    CHECK(msg->findInt64("timeUs", &timeUs));
2447    CHECK(msg->findInt32("flags", (int32_t *)&flags));
2448
2449    const CryptoPlugin::SubSample *subSamples;
2450    size_t numSubSamples;
2451    const uint8_t *key;
2452    const uint8_t *iv;
2453    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2454
2455    // We allow the simpler queueInputBuffer API to be used even in
2456    // secure mode, by fabricating a single unencrypted subSample.
2457    CryptoPlugin::SubSample ss;
2458    CryptoPlugin::Pattern pattern;
2459
2460    if (msg->findSize("size", &size)) {
2461        if (mCrypto != NULL) {
2462            ss.mNumBytesOfClearData = size;
2463            ss.mNumBytesOfEncryptedData = 0;
2464
2465            subSamples = &ss;
2466            numSubSamples = 1;
2467            key = NULL;
2468            iv = NULL;
2469            pattern.mEncryptBlocks = 0;
2470            pattern.mSkipBlocks = 0;
2471        }
2472    } else {
2473        if (mCrypto == NULL) {
2474            return -EINVAL;
2475        }
2476
2477        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2478        CHECK(msg->findSize("numSubSamples", &numSubSamples));
2479        CHECK(msg->findPointer("key", (void **)&key));
2480        CHECK(msg->findPointer("iv", (void **)&iv));
2481        CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2482        CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2483
2484        int32_t tmp;
2485        CHECK(msg->findInt32("mode", &tmp));
2486
2487        mode = (CryptoPlugin::Mode)tmp;
2488
2489        size = 0;
2490        for (size_t i = 0; i < numSubSamples; ++i) {
2491            size += subSamples[i].mNumBytesOfClearData;
2492            size += subSamples[i].mNumBytesOfEncryptedData;
2493        }
2494    }
2495
2496    if (index >= mPortBuffers[kPortIndexInput].size()) {
2497        return -ERANGE;
2498    }
2499
2500    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2501
2502    if (info->mNotify == NULL || !info->mOwnedByClient) {
2503        return -EACCES;
2504    }
2505
2506    if (offset + size > info->mData->capacity()) {
2507        return -EINVAL;
2508    }
2509
2510    sp<AMessage> reply = info->mNotify;
2511    info->mData->setRange(offset, size);
2512
2513    sp<MediaCodecBuffer> buffer = info->mData;
2514    if (mCrypto != NULL) {
2515        AString *errorDetailMsg;
2516        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2517
2518        void *dst_pointer = nullptr;
2519        ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
2520
2521        if ((mFlags & kFlagIsSecure) == 0) {
2522            dst_pointer = info->mSecureData->base();
2523            dst_type = ICrypto::kDestinationTypeVmPointer;
2524        } else {
2525            sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get());
2526            dst_pointer = secureData->getDestinationPointer();
2527            dst_type = secureData->getDestinationType();
2528        }
2529
2530        ssize_t result = mCrypto->decrypt(
2531                dst_type,
2532                key,
2533                iv,
2534                mode,
2535                pattern,
2536                info->mSharedEncryptedBuffer,
2537                offset,
2538                subSamples,
2539                numSubSamples,
2540                dst_pointer,
2541                errorDetailMsg);
2542
2543        if (result < 0) {
2544            return result;
2545        }
2546
2547        info->mSecureData->setRange(0, result);
2548        buffer = info->mSecureData;
2549    }
2550    buffer->meta()->setInt64("timeUs", timeUs);
2551
2552    if (flags & BUFFER_FLAG_EOS) {
2553        buffer->meta()->setInt32("eos", true);
2554    }
2555
2556    if (flags & BUFFER_FLAG_CODECCONFIG) {
2557        buffer->meta()->setInt32("csd", true);
2558    }
2559
2560    // synchronization boundary for getBufferAndFormat
2561    {
2562        Mutex::Autolock al(mBufferLock);
2563        info->mOwnedByClient = false;
2564    }
2565    info->mData.clear();
2566    info->mSecureData.clear();
2567    reply->setObject("buffer", buffer);
2568    reply->post();
2569
2570    info->mNotify = NULL;
2571
2572    return OK;
2573}
2574
2575//static
2576size_t MediaCodec::CreateFramesRenderedMessage(
2577        const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
2578    size_t index = 0;
2579
2580    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2581            it != done.cend(); ++it) {
2582        if (it->getRenderTimeNs() < 0) {
2583            continue; // dropped frame from tracking
2584        }
2585        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2586        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2587        ++index;
2588    }
2589    return index;
2590}
2591
2592status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2593    size_t index;
2594    CHECK(msg->findSize("index", &index));
2595
2596    int32_t render;
2597    if (!msg->findInt32("render", &render)) {
2598        render = 0;
2599    }
2600
2601    if (!isExecuting()) {
2602        return -EINVAL;
2603    }
2604
2605    if (index >= mPortBuffers[kPortIndexOutput].size()) {
2606        return -ERANGE;
2607    }
2608
2609    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2610
2611    if (info->mNotify == NULL || !info->mOwnedByClient) {
2612        return -EACCES;
2613    }
2614
2615    // synchronization boundary for getBufferAndFormat
2616    {
2617        Mutex::Autolock al(mBufferLock);
2618        info->mOwnedByClient = false;
2619    }
2620
2621    if (render && info->mData != NULL && info->mData->size() != 0) {
2622        info->mNotify->setInt32("render", true);
2623
2624        int64_t mediaTimeUs = -1;
2625        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2626
2627        int64_t renderTimeNs = 0;
2628        if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2629            // use media timestamp if client did not request a specific render timestamp
2630            ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2631            renderTimeNs = mediaTimeUs * 1000;
2632        }
2633        info->mNotify->setInt64("timestampNs", renderTimeNs);
2634
2635        if (mSoftRenderer != NULL) {
2636            std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2637                    info->mData->data(), info->mData->size(),
2638                    mediaTimeUs, renderTimeNs, NULL, info->mData->format());
2639
2640            // if we are running, notify rendered frames
2641            if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2642                sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2643                sp<AMessage> data = new AMessage;
2644                if (CreateFramesRenderedMessage(doneFrames, data)) {
2645                    notify->setMessage("data", data);
2646                    notify->post();
2647                }
2648            }
2649        }
2650    }
2651
2652    info->mNotify->setObject("buffer", info->mData);
2653    info->mData.clear();
2654    info->mNotify->post();
2655    info->mNotify.clear();
2656
2657    return OK;
2658}
2659
2660ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2661    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2662
2663    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2664
2665    if (availBuffers->empty()) {
2666        return -EAGAIN;
2667    }
2668
2669    size_t index = *availBuffers->begin();
2670    availBuffers->erase(availBuffers->begin());
2671
2672    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2673    CHECK(!info->mOwnedByClient);
2674    {
2675        Mutex::Autolock al(mBufferLock);
2676        info->mOwnedByClient = true;
2677
2678        // set image-data
2679        if (info->mData->format() != NULL) {
2680            sp<ABuffer> imageData;
2681            if (info->mData->format()->findBuffer("image-data", &imageData)) {
2682                info->mData->meta()->setBuffer("image-data", imageData);
2683            }
2684            int32_t left, top, right, bottom;
2685            if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) {
2686                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2687            }
2688        }
2689    }
2690
2691    return index;
2692}
2693
2694status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2695    status_t err = OK;
2696    if (surface != NULL) {
2697        uint64_t oldId, newId;
2698        if (mSurface != NULL
2699                && surface->getUniqueId(&newId) == NO_ERROR
2700                && mSurface->getUniqueId(&oldId) == NO_ERROR
2701                && newId == oldId) {
2702            ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
2703            return ALREADY_EXISTS;
2704        }
2705
2706        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2707        if (err == OK) {
2708            // Require a fresh set of buffers after each connect by using a unique generation
2709            // number. Rely on the fact that max supported process id by Linux is 2^22.
2710            // PID is never 0 so we don't have to worry that we use the default generation of 0.
2711            // TODO: come up with a unique scheme if other producers also set the generation number.
2712            static uint32_t mSurfaceGeneration = 0;
2713            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2714            surface->setGenerationNumber(generation);
2715            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2716
2717            // HACK: clear any free buffers. Remove when connect will automatically do this.
2718            // This is needed as the consumer may be holding onto stale frames that it can reattach
2719            // to this surface after disconnect/connect, and those free frames would inherit the new
2720            // generation number. Disconnecting after setting a unique generation prevents this.
2721            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2722            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2723        }
2724
2725        if (err != OK) {
2726            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2727        }
2728    }
2729    // do not return ALREADY_EXISTS unless surfaces are the same
2730    return err == ALREADY_EXISTS ? BAD_VALUE : err;
2731}
2732
2733status_t MediaCodec::disconnectFromSurface() {
2734    status_t err = OK;
2735    if (mSurface != NULL) {
2736        // Resetting generation is not technically needed, but there is no need to keep it either
2737        mSurface->setGenerationNumber(0);
2738        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2739        if (err != OK) {
2740            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2741        }
2742        // assume disconnected even on error
2743        mSurface.clear();
2744    }
2745    return err;
2746}
2747
2748status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2749    status_t err = OK;
2750    if (mSurface != NULL) {
2751        (void)disconnectFromSurface();
2752    }
2753    if (surface != NULL) {
2754        err = connectToSurface(surface);
2755        if (err == OK) {
2756            mSurface = surface;
2757        }
2758    }
2759    return err;
2760}
2761
2762void MediaCodec::onInputBufferAvailable() {
2763    int32_t index;
2764    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2765        sp<AMessage> msg = mCallback->dup();
2766        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2767        msg->setInt32("index", index);
2768        msg->post();
2769    }
2770}
2771
2772void MediaCodec::onOutputBufferAvailable() {
2773    int32_t index;
2774    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2775        const sp<MediaCodecBuffer> &buffer =
2776            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2777        sp<AMessage> msg = mCallback->dup();
2778        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2779        msg->setInt32("index", index);
2780        msg->setSize("offset", buffer->offset());
2781        msg->setSize("size", buffer->size());
2782
2783        int64_t timeUs;
2784        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2785
2786        msg->setInt64("timeUs", timeUs);
2787
2788        int32_t omxFlags;
2789        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2790
2791        uint32_t flags = 0;
2792        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2793            flags |= BUFFER_FLAG_SYNCFRAME;
2794        }
2795        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2796            flags |= BUFFER_FLAG_CODECCONFIG;
2797        }
2798        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2799            flags |= BUFFER_FLAG_EOS;
2800        }
2801
2802        msg->setInt32("flags", flags);
2803
2804        msg->post();
2805    }
2806}
2807
2808void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2809    if (mCallback != NULL) {
2810        sp<AMessage> msg = mCallback->dup();
2811        msg->setInt32("callbackID", CB_ERROR);
2812        msg->setInt32("err", err);
2813        msg->setInt32("actionCode", actionCode);
2814
2815        if (detail != NULL) {
2816            msg->setString("detail", detail);
2817        }
2818
2819        msg->post();
2820    }
2821}
2822
2823void MediaCodec::onOutputFormatChanged() {
2824    if (mCallback != NULL) {
2825        sp<AMessage> msg = mCallback->dup();
2826        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2827        msg->setMessage("format", mOutputFormat);
2828        msg->post();
2829    }
2830}
2831
2832
2833void MediaCodec::postActivityNotificationIfPossible() {
2834    if (mActivityNotify == NULL) {
2835        return;
2836    }
2837
2838    bool isErrorOrOutputChanged =
2839            (mFlags & (kFlagStickyError
2840                    | kFlagOutputBuffersChanged
2841                    | kFlagOutputFormatChanged));
2842
2843    if (isErrorOrOutputChanged
2844            || !mAvailPortBuffers[kPortIndexInput].empty()
2845            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2846        mActivityNotify->setInt32("input-buffers",
2847                mAvailPortBuffers[kPortIndexInput].size());
2848
2849        if (isErrorOrOutputChanged) {
2850            // we want consumer to dequeue as many times as it can
2851            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2852        } else {
2853            mActivityNotify->setInt32("output-buffers",
2854                    mAvailPortBuffers[kPortIndexOutput].size());
2855        }
2856        mActivityNotify->post();
2857        mActivityNotify.clear();
2858    }
2859}
2860
2861status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2862    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2863    msg->setMessage("params", params);
2864
2865    sp<AMessage> response;
2866    return PostAndAwaitResponse(msg, &response);
2867}
2868
2869status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2870    mCodec->signalSetParameters(params);
2871
2872    return OK;
2873}
2874
2875status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2876        const sp<MediaCodecBuffer> &buffer) {
2877    AString mime;
2878    CHECK(mOutputFormat->findString("mime", &mime));
2879
2880    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2881        // Codec specific data should be SPS and PPS in a single buffer,
2882        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2883        // We separate the two and put them into the output format
2884        // under the keys "csd-0" and "csd-1".
2885
2886        unsigned csdIndex = 0;
2887
2888        const uint8_t *data = buffer->data();
2889        size_t size = buffer->size();
2890
2891        const uint8_t *nalStart;
2892        size_t nalSize;
2893        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2894            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2895            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2896            memcpy(csd->data() + 4, nalStart, nalSize);
2897
2898            mOutputFormat->setBuffer(
2899                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2900
2901            ++csdIndex;
2902        }
2903
2904        if (csdIndex != 2) {
2905            return ERROR_MALFORMED;
2906        }
2907    } else {
2908        // For everything else we just stash the codec specific data into
2909        // the output format as a single piece of csd under "csd-0".
2910        sp<ABuffer> csd = new ABuffer(buffer->size());
2911        memcpy(csd->data(), buffer->data(), buffer->size());
2912        csd->setRange(0, buffer->size());
2913        mOutputFormat->setBuffer("csd-0", csd);
2914    }
2915
2916    return OK;
2917}
2918
2919void MediaCodec::updateBatteryStat() {
2920    if (!mIsVideo) {
2921        return;
2922    }
2923
2924    if (mState == CONFIGURED && !mBatteryStatNotified) {
2925        BatteryNotifier::getInstance().noteStartVideo(mUid);
2926        mBatteryStatNotified = true;
2927    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2928        BatteryNotifier::getInstance().noteStopVideo(mUid);
2929        mBatteryStatNotified = false;
2930    }
2931}
2932
2933}  // namespace android
2934