MediaCodec.cpp revision 29b7dcf6d3cdb97103467dc8106151c6260c239a
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::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
847    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
848    msg->setInt32("portIndex", kPortIndexInput);
849    msg->setPointer("buffers", buffers);
850
851    sp<AMessage> response;
852    return PostAndAwaitResponse(msg, &response);
853}
854
855status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
856    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
857    msg->setInt32("portIndex", kPortIndexOutput);
858    msg->setPointer("buffers", buffers);
859
860    sp<AMessage> response;
861    return PostAndAwaitResponse(msg, &response);
862}
863
864status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
865    sp<AMessage> format;
866    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
867}
868
869status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
870    sp<MediaCodecBuffer> buffer;
871    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
872}
873
874status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
875    sp<AMessage> format;
876    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
877}
878
879bool MediaCodec::isExecuting() const {
880    return mState == STARTED || mState == FLUSHED;
881}
882
883status_t MediaCodec::getBufferAndFormat(
884        size_t portIndex, size_t index,
885        sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
886    // use mutex instead of a context switch
887    if (mReleasedByResourceManager) {
888        ALOGE("getBufferAndFormat - resource already released");
889        return DEAD_OBJECT;
890    }
891
892    if (buffer == NULL) {
893        ALOGE("getBufferAndFormat - null MediaCodecBuffer");
894        return INVALID_OPERATION;
895    }
896
897    if (format == NULL) {
898        ALOGE("getBufferAndFormat - null AMessage");
899        return INVALID_OPERATION;
900    }
901
902    buffer->clear();
903    format->clear();
904
905    if (!isExecuting()) {
906        ALOGE("getBufferAndFormat - not executing");
907        return INVALID_OPERATION;
908    }
909
910    // we do not want mPortBuffers to change during this section
911    // we also don't want mOwnedByClient to change during this
912    Mutex::Autolock al(mBufferLock);
913
914    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
915    if (index >= buffers->size()) {
916        ALOGE("getBufferAndFormat - trying to get buffer with "
917              "bad index (index=%zu buffer_size=%zu)", index, buffers->size());
918        return INVALID_OPERATION;
919    }
920
921    const BufferInfo &info = buffers->itemAt(index);
922    if (!info.mOwnedByClient) {
923        ALOGE("getBufferAndFormat - invalid operation "
924              "(the index %zu is not owned by client)", index);
925        return INVALID_OPERATION;
926    }
927
928    *buffer = info.mData;
929    *format = info.mData->format();
930
931    return OK;
932}
933
934status_t MediaCodec::flush() {
935    sp<AMessage> msg = new AMessage(kWhatFlush, this);
936
937    sp<AMessage> response;
938    return PostAndAwaitResponse(msg, &response);
939}
940
941status_t MediaCodec::requestIDRFrame() {
942    (new AMessage(kWhatRequestIDRFrame, this))->post();
943
944    return OK;
945}
946
947void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
948    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
949    msg->setMessage("notify", notify);
950    msg->post();
951}
952
953////////////////////////////////////////////////////////////////////////////////
954
955void MediaCodec::cancelPendingDequeueOperations() {
956    if (mFlags & kFlagDequeueInputPending) {
957        PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
958
959        ++mDequeueInputTimeoutGeneration;
960        mDequeueInputReplyID = 0;
961        mFlags &= ~kFlagDequeueInputPending;
962    }
963
964    if (mFlags & kFlagDequeueOutputPending) {
965        PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
966
967        ++mDequeueOutputTimeoutGeneration;
968        mDequeueOutputReplyID = 0;
969        mFlags &= ~kFlagDequeueOutputPending;
970    }
971}
972
973bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
974    if (!isExecuting() || (mFlags & kFlagIsAsync)
975            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
976        PostReplyWithError(replyID, INVALID_OPERATION);
977        return true;
978    } else if (mFlags & kFlagStickyError) {
979        PostReplyWithError(replyID, getStickyError());
980        return true;
981    }
982
983    ssize_t index = dequeuePortBuffer(kPortIndexInput);
984
985    if (index < 0) {
986        CHECK_EQ(index, -EAGAIN);
987        return false;
988    }
989
990    sp<AMessage> response = new AMessage;
991    response->setSize("index", index);
992    response->postReply(replyID);
993
994    return true;
995}
996
997bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
998    if (!isExecuting() || (mFlags & kFlagIsAsync)
999            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
1000        PostReplyWithError(replyID, INVALID_OPERATION);
1001    } else if (mFlags & kFlagStickyError) {
1002        PostReplyWithError(replyID, getStickyError());
1003    } else if (mFlags & kFlagOutputBuffersChanged) {
1004        PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
1005        mFlags &= ~kFlagOutputBuffersChanged;
1006    } else if (mFlags & kFlagOutputFormatChanged) {
1007        PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
1008        mFlags &= ~kFlagOutputFormatChanged;
1009    } else {
1010        sp<AMessage> response = new AMessage;
1011        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
1012
1013        if (index < 0) {
1014            CHECK_EQ(index, -EAGAIN);
1015            return false;
1016        }
1017
1018        const sp<MediaCodecBuffer> &buffer =
1019            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
1020
1021        response->setSize("index", index);
1022        response->setSize("offset", buffer->offset());
1023        response->setSize("size", buffer->size());
1024
1025        int64_t timeUs;
1026        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1027
1028        response->setInt64("timeUs", timeUs);
1029
1030        int32_t omxFlags;
1031        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
1032
1033        uint32_t flags = 0;
1034        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
1035            flags |= BUFFER_FLAG_SYNCFRAME;
1036        }
1037        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1038            flags |= BUFFER_FLAG_CODECCONFIG;
1039        }
1040        if (omxFlags & OMX_BUFFERFLAG_EOS) {
1041            flags |= BUFFER_FLAG_EOS;
1042        }
1043
1044        response->setInt32("flags", flags);
1045        response->postReply(replyID);
1046    }
1047
1048    return true;
1049}
1050
1051void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
1052    switch (msg->what()) {
1053        case kWhatCodecNotify:
1054        {
1055            int32_t what;
1056            CHECK(msg->findInt32("what", &what));
1057
1058            switch (what) {
1059                case CodecBase::kWhatError:
1060                {
1061                    int32_t err, actionCode;
1062                    CHECK(msg->findInt32("err", &err));
1063                    CHECK(msg->findInt32("actionCode", &actionCode));
1064
1065                    ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
1066                            err, actionCode, mState);
1067                    if (err == DEAD_OBJECT) {
1068                        mFlags |= kFlagSawMediaServerDie;
1069                        mFlags &= ~kFlagIsComponentAllocated;
1070                    }
1071
1072                    bool sendErrorResponse = true;
1073
1074                    switch (mState) {
1075                        case INITIALIZING:
1076                        {
1077                            setState(UNINITIALIZED);
1078                            break;
1079                        }
1080
1081                        case CONFIGURING:
1082                        {
1083                            setState(actionCode == ACTION_CODE_FATAL ?
1084                                    UNINITIALIZED : INITIALIZED);
1085                            break;
1086                        }
1087
1088                        case STARTING:
1089                        {
1090                            setState(actionCode == ACTION_CODE_FATAL ?
1091                                    UNINITIALIZED : CONFIGURED);
1092                            break;
1093                        }
1094
1095                        case RELEASING:
1096                        {
1097                            // Ignore the error, assuming we'll still get
1098                            // the shutdown complete notification. If we
1099                            // don't, we'll timeout and force release.
1100                            sendErrorResponse = false;
1101                        }
1102                        // fall-thru
1103                        case STOPPING:
1104                        {
1105                            if (mFlags & kFlagSawMediaServerDie) {
1106                                // MediaServer died, there definitely won't
1107                                // be a shutdown complete notification after
1108                                // all.
1109
1110                                // note that we're directly going from
1111                                // STOPPING->UNINITIALIZED, instead of the
1112                                // usual STOPPING->INITIALIZED state.
1113                                setState(UNINITIALIZED);
1114                                if (mState == RELEASING) {
1115                                    mComponentName.clear();
1116                                }
1117                                (new AMessage)->postReply(mReplyID);
1118                                sendErrorResponse = false;
1119                            }
1120                            break;
1121                        }
1122
1123                        case FLUSHING:
1124                        {
1125                            if (actionCode == ACTION_CODE_FATAL) {
1126                                setState(UNINITIALIZED);
1127                            } else {
1128                                setState(
1129                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
1130                            }
1131                            break;
1132                        }
1133
1134                        case FLUSHED:
1135                        case STARTED:
1136                        {
1137                            sendErrorResponse = false;
1138
1139                            setStickyError(err);
1140                            postActivityNotificationIfPossible();
1141
1142                            cancelPendingDequeueOperations();
1143
1144                            if (mFlags & kFlagIsAsync) {
1145                                onError(err, actionCode);
1146                            }
1147                            switch (actionCode) {
1148                            case ACTION_CODE_TRANSIENT:
1149                                break;
1150                            case ACTION_CODE_RECOVERABLE:
1151                                setState(INITIALIZED);
1152                                break;
1153                            default:
1154                                setState(UNINITIALIZED);
1155                                break;
1156                            }
1157                            break;
1158                        }
1159
1160                        default:
1161                        {
1162                            sendErrorResponse = false;
1163
1164                            setStickyError(err);
1165                            postActivityNotificationIfPossible();
1166
1167                            // actionCode in an uninitialized state is always fatal.
1168                            if (mState == UNINITIALIZED) {
1169                                actionCode = ACTION_CODE_FATAL;
1170                            }
1171                            if (mFlags & kFlagIsAsync) {
1172                                onError(err, actionCode);
1173                            }
1174                            switch (actionCode) {
1175                            case ACTION_CODE_TRANSIENT:
1176                                break;
1177                            case ACTION_CODE_RECOVERABLE:
1178                                setState(INITIALIZED);
1179                                break;
1180                            default:
1181                                setState(UNINITIALIZED);
1182                                break;
1183                            }
1184                            break;
1185                        }
1186                    }
1187
1188                    if (sendErrorResponse) {
1189                        PostReplyWithError(mReplyID, err);
1190                    }
1191                    break;
1192                }
1193
1194                case CodecBase::kWhatComponentAllocated:
1195                {
1196                    CHECK_EQ(mState, INITIALIZING);
1197                    setState(INITIALIZED);
1198                    mFlags |= kFlagIsComponentAllocated;
1199
1200                    CHECK(msg->findString("componentName", &mComponentName));
1201
1202                    if (mComponentName.startsWith("OMX.google.")) {
1203                        mFlags |= kFlagUsesSoftwareRenderer;
1204                    } else {
1205                        mFlags &= ~kFlagUsesSoftwareRenderer;
1206                    }
1207
1208                    MediaResource::Type resourceType;
1209                    if (mComponentName.endsWith(".secure")) {
1210                        mFlags |= kFlagIsSecure;
1211                        resourceType = MediaResource::kSecureCodec;
1212                    } else {
1213                        mFlags &= ~kFlagIsSecure;
1214                        resourceType = MediaResource::kNonSecureCodec;
1215                    }
1216
1217                    if (mIsVideo) {
1218                        // audio codec is currently ignored.
1219                        addResource(resourceType, MediaResource::kVideoCodec, 1);
1220                    }
1221
1222                    (new AMessage)->postReply(mReplyID);
1223                    break;
1224                }
1225
1226                case CodecBase::kWhatComponentConfigured:
1227                {
1228                    if (mState == UNINITIALIZED || mState == INITIALIZED) {
1229                        // In case a kWhatError message came in and replied with error,
1230                        // we log a warning and ignore.
1231                        ALOGW("configure interrupted by error, current state %d", mState);
1232                        break;
1233                    }
1234                    CHECK_EQ(mState, CONFIGURING);
1235
1236                    // reset input surface flag
1237                    mHaveInputSurface = false;
1238
1239                    CHECK(msg->findMessage("input-format", &mInputFormat));
1240                    CHECK(msg->findMessage("output-format", &mOutputFormat));
1241                    ALOGV("[%s] configured as input format: %s, output format: %s",
1242                            mComponentName.c_str(),
1243                            mInputFormat->debugString(4).c_str(),
1244                            mOutputFormat->debugString(4).c_str());
1245                    int32_t usingSwRenderer;
1246                    if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
1247                            && usingSwRenderer) {
1248                        mFlags |= kFlagUsesSoftwareRenderer;
1249                    }
1250                    setState(CONFIGURED);
1251                    (new AMessage)->postReply(mReplyID);
1252                    break;
1253                }
1254
1255                case CodecBase::kWhatInputSurfaceCreated:
1256                {
1257                    // response to initiateCreateInputSurface()
1258                    status_t err = NO_ERROR;
1259                    sp<AMessage> response = new AMessage;
1260                    if (!msg->findInt32("err", &err)) {
1261                        sp<RefBase> obj;
1262                        msg->findObject("input-surface", &obj);
1263                        CHECK(msg->findMessage("input-format", &mInputFormat));
1264                        CHECK(msg->findMessage("output-format", &mOutputFormat));
1265                        ALOGV("[%s] input surface created as input format: %s, output format: %s",
1266                                mComponentName.c_str(),
1267                                mInputFormat->debugString(4).c_str(),
1268                                mOutputFormat->debugString(4).c_str());
1269                        CHECK(obj != NULL);
1270                        response->setObject("input-surface", obj);
1271                        mHaveInputSurface = true;
1272                    } else {
1273                        response->setInt32("err", err);
1274                    }
1275                    response->postReply(mReplyID);
1276                    break;
1277                }
1278
1279                case CodecBase::kWhatInputSurfaceAccepted:
1280                {
1281                    // response to initiateSetInputSurface()
1282                    status_t err = NO_ERROR;
1283                    sp<AMessage> response = new AMessage();
1284                    if (!msg->findInt32("err", &err)) {
1285                        CHECK(msg->findMessage("input-format", &mInputFormat));
1286                        CHECK(msg->findMessage("output-format", &mOutputFormat));
1287                        mHaveInputSurface = true;
1288                    } else {
1289                        response->setInt32("err", err);
1290                    }
1291                    response->postReply(mReplyID);
1292                    break;
1293                }
1294
1295                case CodecBase::kWhatSignaledInputEOS:
1296                {
1297                    // response to signalEndOfInputStream()
1298                    sp<AMessage> response = new AMessage;
1299                    status_t err;
1300                    if (msg->findInt32("err", &err)) {
1301                        response->setInt32("err", err);
1302                    }
1303                    response->postReply(mReplyID);
1304                    break;
1305                }
1306
1307
1308                case CodecBase::kWhatBuffersAllocated:
1309                {
1310                    Mutex::Autolock al(mBufferLock);
1311                    int32_t portIndex;
1312                    CHECK(msg->findInt32("portIndex", &portIndex));
1313
1314                    ALOGV("%s buffers allocated",
1315                          portIndex == kPortIndexInput ? "input" : "output");
1316
1317                    CHECK(portIndex == kPortIndexInput
1318                            || portIndex == kPortIndexOutput);
1319
1320                    mPortBuffers[portIndex].clear();
1321                    mPortBufferArrays[portIndex].clear();
1322
1323                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1324
1325                    sp<RefBase> obj;
1326                    CHECK(msg->findObject("portDesc", &obj));
1327
1328                    sp<CodecBase::PortDescription> portDesc =
1329                        static_cast<CodecBase::PortDescription *>(obj.get());
1330
1331                    size_t numBuffers = portDesc->countBuffers();
1332
1333                    size_t totalSize = 0;
1334                    for (size_t i = 0; i < numBuffers; ++i) {
1335                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1336                            totalSize += portDesc->bufferAt(i)->capacity();
1337                        }
1338                    }
1339
1340                    if (totalSize) {
1341                        mDealer = new MemoryDealer(totalSize, "MediaCodec");
1342                    }
1343
1344                    for (size_t i = 0; i < numBuffers; ++i) {
1345                        BufferInfo info;
1346                        info.mBufferID = portDesc->bufferIDAt(i);
1347                        info.mOwnedByClient = false;
1348                        sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i);
1349                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1350                            info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity());
1351                            buffer = new SharedMemoryBuffer(
1352                                    mInputFormat, info.mSharedEncryptedBuffer);
1353                        }
1354                        buffers->push_back(info);
1355                        mPortBufferArrays[portIndex].push_back(buffer);
1356                    }
1357
1358                    if (portIndex == kPortIndexOutput) {
1359                        if (mState == STARTING) {
1360                            // We're always allocating output buffers after
1361                            // allocating input buffers, so this is a good
1362                            // indication that now all buffers are allocated.
1363                            if (mIsVideo) {
1364                                addResource(
1365                                        MediaResource::kGraphicMemory,
1366                                        MediaResource::kUnspecifiedSubType,
1367                                        getGraphicBufferSize());
1368                            }
1369                            setState(STARTED);
1370                            (new AMessage)->postReply(mReplyID);
1371                        } else {
1372                            mFlags |= kFlagOutputBuffersChanged;
1373                            postActivityNotificationIfPossible();
1374                        }
1375                    }
1376                    break;
1377                }
1378
1379                case CodecBase::kWhatOutputFramesRendered:
1380                {
1381                    // ignore these in all states except running, and check that we have a
1382                    // notification set
1383                    if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1384                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1385                        notify->setMessage("data", msg);
1386                        notify->post();
1387                    }
1388                    break;
1389                }
1390
1391                case CodecBase::kWhatFillThisBuffer:
1392                {
1393                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1394
1395                    if (mState == FLUSHING
1396                            || mState == STOPPING
1397                            || mState == RELEASING) {
1398                        returnBuffersToCodecOnPort(kPortIndexInput);
1399                        break;
1400                    }
1401
1402                    // TODO: hold reference of buffer from downstream when
1403                    // mPortBuffers is removed.
1404
1405                    if (!mCSD.empty()) {
1406                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1407                        CHECK_GE(index, 0);
1408
1409                        // If codec specific data had been specified as
1410                        // part of the format in the call to configure and
1411                        // if there's more csd left, we submit it here
1412                        // clients only get access to input buffers once
1413                        // this data has been exhausted.
1414
1415                        status_t err = queueCSDInputBuffer(index);
1416
1417                        if (err != OK) {
1418                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1419                                  err);
1420
1421                            setStickyError(err);
1422                            postActivityNotificationIfPossible();
1423
1424                            cancelPendingDequeueOperations();
1425                        }
1426                        break;
1427                    }
1428
1429                    if (mFlags & kFlagIsAsync) {
1430                        if (!mHaveInputSurface) {
1431                            if (mState == FLUSHED) {
1432                                mHavePendingInputBuffers = true;
1433                            } else {
1434                                onInputBufferAvailable();
1435                            }
1436                        }
1437                    } else if (mFlags & kFlagDequeueInputPending) {
1438                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1439
1440                        ++mDequeueInputTimeoutGeneration;
1441                        mFlags &= ~kFlagDequeueInputPending;
1442                        mDequeueInputReplyID = 0;
1443                    } else {
1444                        postActivityNotificationIfPossible();
1445                    }
1446                    break;
1447                }
1448
1449                case CodecBase::kWhatDrainThisBuffer:
1450                {
1451                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1452
1453                    if (mState == FLUSHING
1454                            || mState == STOPPING
1455                            || mState == RELEASING) {
1456                        returnBuffersToCodecOnPort(kPortIndexOutput);
1457                        break;
1458                    }
1459
1460                    sp<RefBase> obj;
1461                    CHECK(msg->findObject("buffer", &obj));
1462                    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
1463                    // TODO: hold buffer's reference when we remove mPortBuffers
1464
1465                    int32_t omxFlags;
1466                    CHECK(msg->findInt32("flags", &omxFlags));
1467
1468                    buffer->meta()->setInt32("omxFlags", omxFlags);
1469                    if (mOutputFormat != buffer->format()) {
1470                        mOutputFormat = buffer->format();
1471                        ALOGV("[%s] output format changed to: %s",
1472                                mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
1473
1474                        if (mSoftRenderer == NULL &&
1475                                mSurface != NULL &&
1476                                (mFlags & kFlagUsesSoftwareRenderer)) {
1477                            AString mime;
1478                            CHECK(mOutputFormat->findString("mime", &mime));
1479
1480                            // TODO: propagate color aspects to software renderer to allow better
1481                            // color conversion to RGB. For now, just mark dataspace for YUV
1482                            // rendering.
1483                            int32_t dataSpace;
1484                            if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
1485                                ALOGD("[%s] setting dataspace on output surface to #%x",
1486                                        mComponentName.c_str(), dataSpace);
1487                                int err = native_window_set_buffers_data_space(
1488                                        mSurface.get(), (android_dataspace)dataSpace);
1489                                ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
1490                            }
1491
1492                            if (mime.startsWithIgnoreCase("video/")) {
1493                                mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1494                            }
1495                        }
1496
1497                        if (mFlags & kFlagIsEncoder) {
1498                            // Before we announce the format change we should
1499                            // collect codec specific data and amend the output
1500                            // format as necessary.
1501                            if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1502                                status_t err =
1503                                    amendOutputFormatWithCodecSpecificData(buffer);
1504
1505                                if (err != OK) {
1506                                    ALOGE("Codec spit out malformed codec "
1507                                          "specific data!");
1508                                }
1509                            }
1510                        }
1511
1512                        if (mFlags & kFlagIsAsync) {
1513                            onOutputFormatChanged();
1514                        } else {
1515                            mFlags |= kFlagOutputFormatChanged;
1516                            postActivityNotificationIfPossible();
1517                        }
1518
1519                        // Notify mCrypto of video resolution changes
1520                        if (mCrypto != NULL) {
1521                            int32_t left, top, right, bottom, width, height;
1522                            if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1523                                mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1524                            } else if (mOutputFormat->findInt32("width", &width)
1525                                    && mOutputFormat->findInt32("height", &height)) {
1526                                mCrypto->notifyResolution(width, height);
1527                            }
1528                        }
1529                    }
1530
1531                    if (mFlags & kFlagIsAsync) {
1532                        onOutputBufferAvailable();
1533                    } else if (mFlags & kFlagDequeueOutputPending) {
1534                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1535
1536                        ++mDequeueOutputTimeoutGeneration;
1537                        mFlags &= ~kFlagDequeueOutputPending;
1538                        mDequeueOutputReplyID = 0;
1539                    } else {
1540                        postActivityNotificationIfPossible();
1541                    }
1542
1543                    break;
1544                }
1545
1546                case CodecBase::kWhatEOS:
1547                {
1548                    // We already notify the client of this by using the
1549                    // corresponding flag in "onOutputBufferReady".
1550                    break;
1551                }
1552
1553                case CodecBase::kWhatShutdownCompleted:
1554                {
1555                    if (mState == UNINITIALIZED) {
1556                        // Ignore shutdown complete if we're already released.
1557                        break;
1558                    }
1559                    if (mState == STOPPING) {
1560                        setState(INITIALIZED);
1561                    } else {
1562                        CHECK_EQ(mState, RELEASING);
1563                        setState(UNINITIALIZED);
1564                        mComponentName.clear();
1565                    }
1566                    mFlags &= ~kFlagIsComponentAllocated;
1567
1568                    mResourceManagerService->removeResource(getId(mResourceManagerClient));
1569
1570                    (new AMessage)->postReply(mReplyID);
1571                    break;
1572                }
1573
1574                case CodecBase::kWhatFlushCompleted:
1575                {
1576                    if (mState != FLUSHING) {
1577                        ALOGW("received FlushCompleted message in state %d",
1578                                mState);
1579                        break;
1580                    }
1581
1582                    if (mFlags & kFlagIsAsync) {
1583                        setState(FLUSHED);
1584                    } else {
1585                        setState(STARTED);
1586                        mCodec->signalResume();
1587                    }
1588
1589                    (new AMessage)->postReply(mReplyID);
1590                    break;
1591                }
1592
1593                default:
1594                    TRESPASS();
1595            }
1596            break;
1597        }
1598
1599        case kWhatInit:
1600        {
1601            sp<AReplyToken> replyID;
1602            CHECK(msg->senderAwaitsResponse(&replyID));
1603
1604            if (mState != UNINITIALIZED) {
1605                PostReplyWithError(replyID, INVALID_OPERATION);
1606                break;
1607            }
1608
1609            mReplyID = replyID;
1610            setState(INITIALIZING);
1611
1612            AString name;
1613            CHECK(msg->findString("name", &name));
1614
1615            int32_t nameIsType;
1616            int32_t encoder = false;
1617            CHECK(msg->findInt32("nameIsType", &nameIsType));
1618            if (nameIsType) {
1619                CHECK(msg->findInt32("encoder", &encoder));
1620            }
1621
1622            sp<AMessage> format = new AMessage;
1623
1624            if (nameIsType) {
1625                format->setString("mime", name.c_str());
1626                format->setInt32("encoder", encoder);
1627            } else {
1628                format->setString("componentName", name.c_str());
1629            }
1630
1631            mCodec->initiateAllocateComponent(format);
1632            break;
1633        }
1634
1635        case kWhatSetNotification:
1636        {
1637            sp<AMessage> notify;
1638            if (msg->findMessage("on-frame-rendered", &notify)) {
1639                mOnFrameRenderedNotification = notify;
1640            }
1641            break;
1642        }
1643
1644        case kWhatSetCallback:
1645        {
1646            sp<AReplyToken> replyID;
1647            CHECK(msg->senderAwaitsResponse(&replyID));
1648
1649            if (mState == UNINITIALIZED
1650                    || mState == INITIALIZING
1651                    || isExecuting()) {
1652                // callback can't be set after codec is executing,
1653                // or before it's initialized (as the callback
1654                // will be cleared when it goes to INITIALIZED)
1655                PostReplyWithError(replyID, INVALID_OPERATION);
1656                break;
1657            }
1658
1659            sp<AMessage> callback;
1660            CHECK(msg->findMessage("callback", &callback));
1661
1662            mCallback = callback;
1663
1664            if (mCallback != NULL) {
1665                ALOGI("MediaCodec will operate in async mode");
1666                mFlags |= kFlagIsAsync;
1667            } else {
1668                mFlags &= ~kFlagIsAsync;
1669            }
1670
1671            sp<AMessage> response = new AMessage;
1672            response->postReply(replyID);
1673            break;
1674        }
1675
1676        case kWhatConfigure:
1677        {
1678            sp<AReplyToken> replyID;
1679            CHECK(msg->senderAwaitsResponse(&replyID));
1680
1681            if (mState != INITIALIZED) {
1682                PostReplyWithError(replyID, INVALID_OPERATION);
1683                break;
1684            }
1685
1686            sp<RefBase> obj;
1687            CHECK(msg->findObject("surface", &obj));
1688
1689            sp<AMessage> format;
1690            CHECK(msg->findMessage("format", &format));
1691
1692            int32_t push;
1693            if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
1694                mFlags |= kFlagPushBlankBuffersOnShutdown;
1695            }
1696
1697            if (obj != NULL) {
1698                format->setObject("native-window", obj);
1699                status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
1700                if (err != OK) {
1701                    PostReplyWithError(replyID, err);
1702                    break;
1703                }
1704            } else {
1705                handleSetSurface(NULL);
1706            }
1707
1708            mReplyID = replyID;
1709            setState(CONFIGURING);
1710
1711            void *crypto;
1712            if (!msg->findPointer("crypto", &crypto)) {
1713                crypto = NULL;
1714            }
1715
1716            mCrypto = static_cast<ICrypto *>(crypto);
1717
1718            uint32_t flags;
1719            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1720
1721            if (flags & CONFIGURE_FLAG_ENCODE) {
1722                format->setInt32("encoder", true);
1723                mFlags |= kFlagIsEncoder;
1724            }
1725
1726            extractCSD(format);
1727
1728            mCodec->initiateConfigureComponent(format);
1729            break;
1730        }
1731
1732        case kWhatSetSurface:
1733        {
1734            sp<AReplyToken> replyID;
1735            CHECK(msg->senderAwaitsResponse(&replyID));
1736
1737            status_t err = OK;
1738            sp<Surface> surface;
1739
1740            switch (mState) {
1741                case CONFIGURED:
1742                case STARTED:
1743                case FLUSHED:
1744                {
1745                    sp<RefBase> obj;
1746                    (void)msg->findObject("surface", &obj);
1747                    sp<Surface> surface = static_cast<Surface *>(obj.get());
1748                    if (mSurface == NULL) {
1749                        // do not support setting surface if it was not set
1750                        err = INVALID_OPERATION;
1751                    } else if (obj == NULL) {
1752                        // do not support unsetting surface
1753                        err = BAD_VALUE;
1754                    } else {
1755                        err = connectToSurface(surface);
1756                        if (err == ALREADY_EXISTS) {
1757                            // reconnecting to same surface
1758                            err = OK;
1759                        } else {
1760                            if (err == OK) {
1761                                if (mFlags & kFlagUsesSoftwareRenderer) {
1762                                    if (mSoftRenderer != NULL
1763                                            && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1764                                        pushBlankBuffersToNativeWindow(mSurface.get());
1765                                    }
1766                                    mSoftRenderer = new SoftwareRenderer(surface);
1767                                    // TODO: check if this was successful
1768                                } else {
1769                                    err = mCodec->setSurface(surface);
1770                                }
1771                            }
1772                            if (err == OK) {
1773                                (void)disconnectFromSurface();
1774                                mSurface = surface;
1775                            }
1776                        }
1777                    }
1778                    break;
1779                }
1780
1781                default:
1782                    err = INVALID_OPERATION;
1783                    break;
1784            }
1785
1786            PostReplyWithError(replyID, err);
1787            break;
1788        }
1789
1790        case kWhatCreateInputSurface:
1791        case kWhatSetInputSurface:
1792        {
1793            sp<AReplyToken> replyID;
1794            CHECK(msg->senderAwaitsResponse(&replyID));
1795
1796            // Must be configured, but can't have been started yet.
1797            if (mState != CONFIGURED) {
1798                PostReplyWithError(replyID, INVALID_OPERATION);
1799                break;
1800            }
1801
1802            mReplyID = replyID;
1803            if (msg->what() == kWhatCreateInputSurface) {
1804                mCodec->initiateCreateInputSurface();
1805            } else {
1806                sp<RefBase> obj;
1807                CHECK(msg->findObject("input-surface", &obj));
1808
1809                mCodec->initiateSetInputSurface(
1810                        static_cast<PersistentSurface *>(obj.get()));
1811            }
1812            break;
1813        }
1814        case kWhatStart:
1815        {
1816            sp<AReplyToken> replyID;
1817            CHECK(msg->senderAwaitsResponse(&replyID));
1818
1819            if (mState == FLUSHED) {
1820                setState(STARTED);
1821                if (mHavePendingInputBuffers) {
1822                    onInputBufferAvailable();
1823                    mHavePendingInputBuffers = false;
1824                }
1825                mCodec->signalResume();
1826                PostReplyWithError(replyID, OK);
1827                break;
1828            } else if (mState != CONFIGURED) {
1829                PostReplyWithError(replyID, INVALID_OPERATION);
1830                break;
1831            }
1832
1833            mReplyID = replyID;
1834            setState(STARTING);
1835
1836            mCodec->initiateStart();
1837            break;
1838        }
1839
1840        case kWhatStop:
1841        case kWhatRelease:
1842        {
1843            State targetState =
1844                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1845
1846            sp<AReplyToken> replyID;
1847            CHECK(msg->senderAwaitsResponse(&replyID));
1848
1849            // already stopped/released
1850            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
1851                sp<AMessage> response = new AMessage;
1852                response->setInt32("err", OK);
1853                response->postReply(replyID);
1854                break;
1855            }
1856
1857            int32_t reclaimed = 0;
1858            msg->findInt32("reclaimed", &reclaimed);
1859            if (reclaimed) {
1860                mReleasedByResourceManager = true;
1861
1862                int32_t force = 0;
1863                msg->findInt32("force", &force);
1864                if (!force && hasPendingBuffer()) {
1865                    ALOGW("Can't reclaim codec right now due to pending buffers.");
1866
1867                    // return WOULD_BLOCK to ask resource manager to retry later.
1868                    sp<AMessage> response = new AMessage;
1869                    response->setInt32("err", WOULD_BLOCK);
1870                    response->postReply(replyID);
1871
1872                    // notify the async client
1873                    if (mFlags & kFlagIsAsync) {
1874                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
1875                    }
1876                    break;
1877                }
1878            }
1879
1880            bool isReleasingAllocatedComponent =
1881                    (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
1882            if (!isReleasingAllocatedComponent // See 1
1883                    && mState != INITIALIZED
1884                    && mState != CONFIGURED && !isExecuting()) {
1885                // 1) Permit release to shut down the component if allocated.
1886                //
1887                // 2) We may be in "UNINITIALIZED" state already and
1888                // also shutdown the encoder/decoder without the
1889                // client being aware of this if media server died while
1890                // we were being stopped. The client would assume that
1891                // after stop() returned, it would be safe to call release()
1892                // and it should be in this case, no harm to allow a release()
1893                // if we're already uninitialized.
1894                sp<AMessage> response = new AMessage;
1895                // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
1896                // the previous stop/release completes and then reply with OK.
1897                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1898                response->setInt32("err", err);
1899                if (err == OK && targetState == UNINITIALIZED) {
1900                    mComponentName.clear();
1901                }
1902                response->postReply(replyID);
1903                break;
1904            }
1905
1906            // If we're flushing, or we're stopping but received a release
1907            // request, post the reply for the pending call first, and consider
1908            // it done. The reply token will be replaced after this, and we'll
1909            // no longer be able to reply.
1910            if (mState == FLUSHING || mState == STOPPING) {
1911                (new AMessage)->postReply(mReplyID);
1912            }
1913
1914            if (mFlags & kFlagSawMediaServerDie) {
1915                // It's dead, Jim. Don't expect initiateShutdown to yield
1916                // any useful results now...
1917                setState(UNINITIALIZED);
1918                if (targetState == UNINITIALIZED) {
1919                    mComponentName.clear();
1920                }
1921                (new AMessage)->postReply(replyID);
1922                break;
1923            }
1924
1925            // If we already have an error, component may not be able to
1926            // complete the shutdown properly. If we're stopping, post the
1927            // reply now with an error to unblock the client, client can
1928            // release after the failure (instead of ANR).
1929            if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
1930                PostReplyWithError(replyID, getStickyError());
1931                break;
1932            }
1933
1934            mReplyID = replyID;
1935            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1936
1937            mCodec->initiateShutdown(
1938                    msg->what() == kWhatStop /* keepComponentAllocated */);
1939
1940            returnBuffersToCodec(reclaimed);
1941
1942            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1943                pushBlankBuffersToNativeWindow(mSurface.get());
1944            }
1945
1946            break;
1947        }
1948
1949        case kWhatDequeueInputBuffer:
1950        {
1951            sp<AReplyToken> replyID;
1952            CHECK(msg->senderAwaitsResponse(&replyID));
1953
1954            if (mFlags & kFlagIsAsync) {
1955                ALOGE("dequeueOutputBuffer can't be used in async mode");
1956                PostReplyWithError(replyID, INVALID_OPERATION);
1957                break;
1958            }
1959
1960            if (mHaveInputSurface) {
1961                ALOGE("dequeueInputBuffer can't be used with input surface");
1962                PostReplyWithError(replyID, INVALID_OPERATION);
1963                break;
1964            }
1965
1966            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1967                break;
1968            }
1969
1970            int64_t timeoutUs;
1971            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1972
1973            if (timeoutUs == 0ll) {
1974                PostReplyWithError(replyID, -EAGAIN);
1975                break;
1976            }
1977
1978            mFlags |= kFlagDequeueInputPending;
1979            mDequeueInputReplyID = replyID;
1980
1981            if (timeoutUs > 0ll) {
1982                sp<AMessage> timeoutMsg =
1983                    new AMessage(kWhatDequeueInputTimedOut, this);
1984                timeoutMsg->setInt32(
1985                        "generation", ++mDequeueInputTimeoutGeneration);
1986                timeoutMsg->post(timeoutUs);
1987            }
1988            break;
1989        }
1990
1991        case kWhatDequeueInputTimedOut:
1992        {
1993            int32_t generation;
1994            CHECK(msg->findInt32("generation", &generation));
1995
1996            if (generation != mDequeueInputTimeoutGeneration) {
1997                // Obsolete
1998                break;
1999            }
2000
2001            CHECK(mFlags & kFlagDequeueInputPending);
2002
2003            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
2004
2005            mFlags &= ~kFlagDequeueInputPending;
2006            mDequeueInputReplyID = 0;
2007            break;
2008        }
2009
2010        case kWhatQueueInputBuffer:
2011        {
2012            sp<AReplyToken> replyID;
2013            CHECK(msg->senderAwaitsResponse(&replyID));
2014
2015            if (!isExecuting()) {
2016                PostReplyWithError(replyID, INVALID_OPERATION);
2017                break;
2018            } else if (mFlags & kFlagStickyError) {
2019                PostReplyWithError(replyID, getStickyError());
2020                break;
2021            }
2022
2023            status_t err = onQueueInputBuffer(msg);
2024
2025            PostReplyWithError(replyID, err);
2026            break;
2027        }
2028
2029        case kWhatDequeueOutputBuffer:
2030        {
2031            sp<AReplyToken> replyID;
2032            CHECK(msg->senderAwaitsResponse(&replyID));
2033
2034            if (mFlags & kFlagIsAsync) {
2035                ALOGE("dequeueOutputBuffer can't be used in async mode");
2036                PostReplyWithError(replyID, INVALID_OPERATION);
2037                break;
2038            }
2039
2040            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
2041                break;
2042            }
2043
2044            int64_t timeoutUs;
2045            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2046
2047            if (timeoutUs == 0ll) {
2048                PostReplyWithError(replyID, -EAGAIN);
2049                break;
2050            }
2051
2052            mFlags |= kFlagDequeueOutputPending;
2053            mDequeueOutputReplyID = replyID;
2054
2055            if (timeoutUs > 0ll) {
2056                sp<AMessage> timeoutMsg =
2057                    new AMessage(kWhatDequeueOutputTimedOut, this);
2058                timeoutMsg->setInt32(
2059                        "generation", ++mDequeueOutputTimeoutGeneration);
2060                timeoutMsg->post(timeoutUs);
2061            }
2062            break;
2063        }
2064
2065        case kWhatDequeueOutputTimedOut:
2066        {
2067            int32_t generation;
2068            CHECK(msg->findInt32("generation", &generation));
2069
2070            if (generation != mDequeueOutputTimeoutGeneration) {
2071                // Obsolete
2072                break;
2073            }
2074
2075            CHECK(mFlags & kFlagDequeueOutputPending);
2076
2077            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2078
2079            mFlags &= ~kFlagDequeueOutputPending;
2080            mDequeueOutputReplyID = 0;
2081            break;
2082        }
2083
2084        case kWhatReleaseOutputBuffer:
2085        {
2086            sp<AReplyToken> replyID;
2087            CHECK(msg->senderAwaitsResponse(&replyID));
2088
2089            if (!isExecuting()) {
2090                PostReplyWithError(replyID, INVALID_OPERATION);
2091                break;
2092            } else if (mFlags & kFlagStickyError) {
2093                PostReplyWithError(replyID, getStickyError());
2094                break;
2095            }
2096
2097            status_t err = onReleaseOutputBuffer(msg);
2098
2099            PostReplyWithError(replyID, err);
2100            break;
2101        }
2102
2103        case kWhatSignalEndOfInputStream:
2104        {
2105            sp<AReplyToken> replyID;
2106            CHECK(msg->senderAwaitsResponse(&replyID));
2107
2108            if (!isExecuting() || !mHaveInputSurface) {
2109                PostReplyWithError(replyID, INVALID_OPERATION);
2110                break;
2111            } else if (mFlags & kFlagStickyError) {
2112                PostReplyWithError(replyID, getStickyError());
2113                break;
2114            }
2115
2116            mReplyID = replyID;
2117            mCodec->signalEndOfInputStream();
2118            break;
2119        }
2120
2121        case kWhatGetBuffers:
2122        {
2123            sp<AReplyToken> replyID;
2124            CHECK(msg->senderAwaitsResponse(&replyID));
2125            if (!isExecuting() || (mFlags & kFlagIsAsync)) {
2126                PostReplyWithError(replyID, INVALID_OPERATION);
2127                break;
2128            } else if (mFlags & kFlagStickyError) {
2129                PostReplyWithError(replyID, getStickyError());
2130                break;
2131            }
2132
2133            int32_t portIndex;
2134            CHECK(msg->findInt32("portIndex", &portIndex));
2135
2136            Vector<sp<MediaCodecBuffer> > *dstBuffers;
2137            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2138
2139            dstBuffers->clear();
2140            // If we're using input surface (either non-persistent created by
2141            // createInputSurface(), or persistent set by setInputSurface()),
2142            // give the client an empty input buffers array.
2143            if (portIndex != kPortIndexInput || !mHaveInputSurface) {
2144                const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex];
2145
2146                for (size_t i = 0; i < srcBuffers.size(); ++i) {
2147                    dstBuffers->push_back(srcBuffers[i]);
2148                }
2149            }
2150
2151            (new AMessage)->postReply(replyID);
2152            break;
2153        }
2154
2155        case kWhatFlush:
2156        {
2157            sp<AReplyToken> replyID;
2158            CHECK(msg->senderAwaitsResponse(&replyID));
2159
2160            if (!isExecuting()) {
2161                PostReplyWithError(replyID, INVALID_OPERATION);
2162                break;
2163            } else if (mFlags & kFlagStickyError) {
2164                PostReplyWithError(replyID, getStickyError());
2165                break;
2166            }
2167
2168            mReplyID = replyID;
2169            // TODO: skip flushing if already FLUSHED
2170            setState(FLUSHING);
2171
2172            mCodec->signalFlush();
2173            returnBuffersToCodec();
2174            break;
2175        }
2176
2177        case kWhatGetInputFormat:
2178        case kWhatGetOutputFormat:
2179        {
2180            sp<AMessage> format =
2181                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2182
2183            sp<AReplyToken> replyID;
2184            CHECK(msg->senderAwaitsResponse(&replyID));
2185
2186            if ((mState != CONFIGURED && mState != STARTING &&
2187                 mState != STARTED && mState != FLUSHING &&
2188                 mState != FLUSHED)
2189                    || format == NULL) {
2190                PostReplyWithError(replyID, INVALID_OPERATION);
2191                break;
2192            } else if (mFlags & kFlagStickyError) {
2193                PostReplyWithError(replyID, getStickyError());
2194                break;
2195            }
2196
2197            sp<AMessage> response = new AMessage;
2198            response->setMessage("format", format);
2199            response->postReply(replyID);
2200            break;
2201        }
2202
2203        case kWhatRequestIDRFrame:
2204        {
2205            mCodec->signalRequestIDRFrame();
2206            break;
2207        }
2208
2209        case kWhatRequestActivityNotification:
2210        {
2211            CHECK(mActivityNotify == NULL);
2212            CHECK(msg->findMessage("notify", &mActivityNotify));
2213
2214            postActivityNotificationIfPossible();
2215            break;
2216        }
2217
2218        case kWhatGetName:
2219        {
2220            sp<AReplyToken> replyID;
2221            CHECK(msg->senderAwaitsResponse(&replyID));
2222
2223            if (mComponentName.empty()) {
2224                PostReplyWithError(replyID, INVALID_OPERATION);
2225                break;
2226            }
2227
2228            sp<AMessage> response = new AMessage;
2229            response->setString("name", mComponentName.c_str());
2230            response->postReply(replyID);
2231            break;
2232        }
2233
2234        case kWhatSetParameters:
2235        {
2236            sp<AReplyToken> replyID;
2237            CHECK(msg->senderAwaitsResponse(&replyID));
2238
2239            sp<AMessage> params;
2240            CHECK(msg->findMessage("params", &params));
2241
2242            status_t err = onSetParameters(params);
2243
2244            PostReplyWithError(replyID, err);
2245            break;
2246        }
2247
2248        default:
2249            TRESPASS();
2250    }
2251}
2252
2253void MediaCodec::extractCSD(const sp<AMessage> &format) {
2254    mCSD.clear();
2255
2256    size_t i = 0;
2257    for (;;) {
2258        sp<ABuffer> csd;
2259        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2260            break;
2261        }
2262        if (csd->size() == 0) {
2263            ALOGW("csd-%zu size is 0", i);
2264        }
2265
2266        mCSD.push_back(csd);
2267        ++i;
2268    }
2269
2270    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2271}
2272
2273status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2274    CHECK(!mCSD.empty());
2275
2276    const BufferInfo *info =
2277        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2278
2279    sp<ABuffer> csd = *mCSD.begin();
2280    mCSD.erase(mCSD.begin());
2281
2282    const sp<MediaCodecBuffer> &codecInputData = info->mData;
2283
2284    if (csd->size() > codecInputData->capacity()) {
2285        return -EINVAL;
2286    }
2287
2288    memcpy(codecInputData->data(), csd->data(), csd->size());
2289
2290    AString errorDetailMsg;
2291
2292    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2293    msg->setSize("index", bufferIndex);
2294    msg->setSize("offset", 0);
2295    msg->setSize("size", csd->size());
2296    msg->setInt64("timeUs", 0ll);
2297    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2298    msg->setPointer("errorDetailMsg", &errorDetailMsg);
2299
2300    return onQueueInputBuffer(msg);
2301}
2302
2303void MediaCodec::setState(State newState) {
2304    if (newState == INITIALIZED || newState == UNINITIALIZED) {
2305        delete mSoftRenderer;
2306        mSoftRenderer = NULL;
2307
2308        mCrypto.clear();
2309        handleSetSurface(NULL);
2310
2311        mInputFormat.clear();
2312        mOutputFormat.clear();
2313        mFlags &= ~kFlagOutputFormatChanged;
2314        mFlags &= ~kFlagOutputBuffersChanged;
2315        mFlags &= ~kFlagStickyError;
2316        mFlags &= ~kFlagIsEncoder;
2317        mFlags &= ~kFlagIsAsync;
2318        mStickyError = OK;
2319
2320        mActivityNotify.clear();
2321        mCallback.clear();
2322    }
2323
2324    if (newState == UNINITIALIZED) {
2325        // return any straggling buffers, e.g. if we got here on an error
2326        returnBuffersToCodec();
2327
2328        // The component is gone, mediaserver's probably back up already
2329        // but should definitely be back up should we try to instantiate
2330        // another component.. and the cycle continues.
2331        mFlags &= ~kFlagSawMediaServerDie;
2332    }
2333
2334    mState = newState;
2335
2336    cancelPendingDequeueOperations();
2337
2338    updateBatteryStat();
2339}
2340
2341void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2342    returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2343    returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2344}
2345
2346void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2347    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2348    Mutex::Autolock al(mBufferLock);
2349
2350    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2351
2352    for (size_t i = 0; i < buffers->size(); ++i) {
2353        BufferInfo *info = &buffers->editItemAt(i);
2354
2355        if (info->mNotify != NULL) {
2356            sp<AMessage> msg = info->mNotify;
2357            info->mNotify = NULL;
2358            msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL)
2359                    ? info->mSecureData : info->mData);
2360            if (isReclaim && info->mOwnedByClient) {
2361                ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2362                        portIndex, i);
2363            } else {
2364                info->mOwnedByClient = false;
2365                info->mData.clear();
2366                info->mSecureData.clear();
2367            }
2368
2369            if (portIndex == kPortIndexInput) {
2370                /* no error, just returning buffers */
2371                msg->setInt32("err", OK);
2372            }
2373            msg->post();
2374        }
2375    }
2376
2377    mAvailPortBuffers[portIndex].clear();
2378}
2379
2380size_t MediaCodec::updateBuffers(
2381        int32_t portIndex, const sp<AMessage> &msg) {
2382    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2383
2384    uint32_t bufferID;
2385    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2386    sp<RefBase> obj;
2387    CHECK(msg->findObject("buffer", &obj));
2388    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
2389
2390    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2391
2392    for (size_t i = 0; i < buffers->size(); ++i) {
2393        BufferInfo *info = &buffers->editItemAt(i);
2394
2395        if (info->mBufferID == bufferID) {
2396            CHECK(info->mNotify == NULL);
2397            CHECK(msg->findMessage("reply", &info->mNotify));
2398
2399            if (portIndex == kPortIndexInput && mCrypto != NULL) {
2400                info->mSecureData = buffer;
2401                info->mData = mPortBufferArrays[portIndex][i];
2402            } else {
2403                info->mData = buffer;
2404            }
2405            mAvailPortBuffers[portIndex].push_back(i);
2406
2407            return i;
2408        }
2409    }
2410
2411    TRESPASS();
2412
2413    return 0;
2414}
2415
2416status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2417    size_t index;
2418    size_t offset;
2419    size_t size;
2420    int64_t timeUs;
2421    uint32_t flags;
2422    CHECK(msg->findSize("index", &index));
2423    CHECK(msg->findSize("offset", &offset));
2424    CHECK(msg->findInt64("timeUs", &timeUs));
2425    CHECK(msg->findInt32("flags", (int32_t *)&flags));
2426
2427    const CryptoPlugin::SubSample *subSamples;
2428    size_t numSubSamples;
2429    const uint8_t *key;
2430    const uint8_t *iv;
2431    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2432
2433    // We allow the simpler queueInputBuffer API to be used even in
2434    // secure mode, by fabricating a single unencrypted subSample.
2435    CryptoPlugin::SubSample ss;
2436    CryptoPlugin::Pattern pattern;
2437
2438    if (msg->findSize("size", &size)) {
2439        if (mCrypto != NULL) {
2440            ss.mNumBytesOfClearData = size;
2441            ss.mNumBytesOfEncryptedData = 0;
2442
2443            subSamples = &ss;
2444            numSubSamples = 1;
2445            key = NULL;
2446            iv = NULL;
2447            pattern.mEncryptBlocks = 0;
2448            pattern.mSkipBlocks = 0;
2449        }
2450    } else {
2451        if (mCrypto == NULL) {
2452            return -EINVAL;
2453        }
2454
2455        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2456        CHECK(msg->findSize("numSubSamples", &numSubSamples));
2457        CHECK(msg->findPointer("key", (void **)&key));
2458        CHECK(msg->findPointer("iv", (void **)&iv));
2459        CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2460        CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2461
2462        int32_t tmp;
2463        CHECK(msg->findInt32("mode", &tmp));
2464
2465        mode = (CryptoPlugin::Mode)tmp;
2466
2467        size = 0;
2468        for (size_t i = 0; i < numSubSamples; ++i) {
2469            size += subSamples[i].mNumBytesOfClearData;
2470            size += subSamples[i].mNumBytesOfEncryptedData;
2471        }
2472    }
2473
2474    if (index >= mPortBuffers[kPortIndexInput].size()) {
2475        return -ERANGE;
2476    }
2477
2478    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2479
2480    if (info->mNotify == NULL || !info->mOwnedByClient) {
2481        return -EACCES;
2482    }
2483
2484    if (offset + size > info->mData->capacity()) {
2485        return -EINVAL;
2486    }
2487
2488    sp<AMessage> reply = info->mNotify;
2489    info->mData->setRange(offset, size);
2490
2491    sp<MediaCodecBuffer> buffer = info->mData;
2492    if (mCrypto != NULL) {
2493        AString *errorDetailMsg;
2494        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2495
2496        void *dst_pointer = nullptr;
2497        ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
2498
2499        if ((mFlags & kFlagIsSecure) == 0) {
2500            dst_pointer = info->mSecureData->base();
2501            dst_type = ICrypto::kDestinationTypeVmPointer;
2502        } else {
2503            sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get());
2504            dst_pointer = secureData->getDestinationPointer();
2505            dst_type = secureData->getDestinationType();
2506        }
2507
2508        ssize_t result = mCrypto->decrypt(
2509                dst_type,
2510                key,
2511                iv,
2512                mode,
2513                pattern,
2514                info->mSharedEncryptedBuffer,
2515                offset,
2516                subSamples,
2517                numSubSamples,
2518                dst_pointer,
2519                errorDetailMsg);
2520
2521        if (result < 0) {
2522            return result;
2523        }
2524
2525        info->mSecureData->setRange(0, result);
2526        buffer = info->mSecureData;
2527    }
2528    buffer->meta()->setInt64("timeUs", timeUs);
2529
2530    if (flags & BUFFER_FLAG_EOS) {
2531        buffer->meta()->setInt32("eos", true);
2532    }
2533
2534    if (flags & BUFFER_FLAG_CODECCONFIG) {
2535        buffer->meta()->setInt32("csd", true);
2536    }
2537
2538    // synchronization boundary for getBufferAndFormat
2539    {
2540        Mutex::Autolock al(mBufferLock);
2541        info->mOwnedByClient = false;
2542    }
2543    info->mData.clear();
2544    info->mSecureData.clear();
2545    reply->setObject("buffer", buffer);
2546    reply->post();
2547
2548    info->mNotify = NULL;
2549
2550    return OK;
2551}
2552
2553//static
2554size_t MediaCodec::CreateFramesRenderedMessage(
2555        const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
2556    size_t index = 0;
2557
2558    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2559            it != done.cend(); ++it) {
2560        if (it->getRenderTimeNs() < 0) {
2561            continue; // dropped frame from tracking
2562        }
2563        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2564        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2565        ++index;
2566    }
2567    return index;
2568}
2569
2570status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2571    size_t index;
2572    CHECK(msg->findSize("index", &index));
2573
2574    int32_t render;
2575    if (!msg->findInt32("render", &render)) {
2576        render = 0;
2577    }
2578
2579    if (!isExecuting()) {
2580        return -EINVAL;
2581    }
2582
2583    if (index >= mPortBuffers[kPortIndexOutput].size()) {
2584        return -ERANGE;
2585    }
2586
2587    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2588
2589    if (info->mNotify == NULL || !info->mOwnedByClient) {
2590        return -EACCES;
2591    }
2592
2593    // synchronization boundary for getBufferAndFormat
2594    {
2595        Mutex::Autolock al(mBufferLock);
2596        info->mOwnedByClient = false;
2597    }
2598
2599    if (render && info->mData != NULL && info->mData->size() != 0) {
2600        info->mNotify->setInt32("render", true);
2601
2602        int64_t mediaTimeUs = -1;
2603        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2604
2605        int64_t renderTimeNs = 0;
2606        if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2607            // use media timestamp if client did not request a specific render timestamp
2608            ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2609            renderTimeNs = mediaTimeUs * 1000;
2610        }
2611        info->mNotify->setInt64("timestampNs", renderTimeNs);
2612
2613        if (mSoftRenderer != NULL) {
2614            std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2615                    info->mData->data(), info->mData->size(),
2616                    mediaTimeUs, renderTimeNs, NULL, info->mData->format());
2617
2618            // if we are running, notify rendered frames
2619            if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2620                sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2621                sp<AMessage> data = new AMessage;
2622                if (CreateFramesRenderedMessage(doneFrames, data)) {
2623                    notify->setMessage("data", data);
2624                    notify->post();
2625                }
2626            }
2627        }
2628    }
2629
2630    info->mNotify->setObject("buffer", info->mData);
2631    info->mData.clear();
2632    info->mNotify->post();
2633    info->mNotify.clear();
2634
2635    return OK;
2636}
2637
2638ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2639    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2640
2641    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2642
2643    if (availBuffers->empty()) {
2644        return -EAGAIN;
2645    }
2646
2647    size_t index = *availBuffers->begin();
2648    availBuffers->erase(availBuffers->begin());
2649
2650    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2651    CHECK(!info->mOwnedByClient);
2652    {
2653        Mutex::Autolock al(mBufferLock);
2654        info->mOwnedByClient = true;
2655
2656        // set image-data
2657        if (info->mData->format() != NULL) {
2658            sp<ABuffer> imageData;
2659            if (info->mData->format()->findBuffer("image-data", &imageData)) {
2660                info->mData->meta()->setBuffer("image-data", imageData);
2661            }
2662            int32_t left, top, right, bottom;
2663            if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) {
2664                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2665            }
2666        }
2667    }
2668
2669    return index;
2670}
2671
2672status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2673    status_t err = OK;
2674    if (surface != NULL) {
2675        uint64_t oldId, newId;
2676        if (mSurface != NULL
2677                && surface->getUniqueId(&newId) == NO_ERROR
2678                && mSurface->getUniqueId(&oldId) == NO_ERROR
2679                && newId == oldId) {
2680            ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
2681            return ALREADY_EXISTS;
2682        }
2683
2684        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2685        if (err == OK) {
2686            // Require a fresh set of buffers after each connect by using a unique generation
2687            // number. Rely on the fact that max supported process id by Linux is 2^22.
2688            // PID is never 0 so we don't have to worry that we use the default generation of 0.
2689            // TODO: come up with a unique scheme if other producers also set the generation number.
2690            static uint32_t mSurfaceGeneration = 0;
2691            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2692            surface->setGenerationNumber(generation);
2693            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2694
2695            // HACK: clear any free buffers. Remove when connect will automatically do this.
2696            // This is needed as the consumer may be holding onto stale frames that it can reattach
2697            // to this surface after disconnect/connect, and those free frames would inherit the new
2698            // generation number. Disconnecting after setting a unique generation prevents this.
2699            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2700            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2701        }
2702
2703        if (err != OK) {
2704            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2705        }
2706    }
2707    // do not return ALREADY_EXISTS unless surfaces are the same
2708    return err == ALREADY_EXISTS ? BAD_VALUE : err;
2709}
2710
2711status_t MediaCodec::disconnectFromSurface() {
2712    status_t err = OK;
2713    if (mSurface != NULL) {
2714        // Resetting generation is not technically needed, but there is no need to keep it either
2715        mSurface->setGenerationNumber(0);
2716        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2717        if (err != OK) {
2718            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2719        }
2720        // assume disconnected even on error
2721        mSurface.clear();
2722    }
2723    return err;
2724}
2725
2726status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2727    status_t err = OK;
2728    if (mSurface != NULL) {
2729        (void)disconnectFromSurface();
2730    }
2731    if (surface != NULL) {
2732        err = connectToSurface(surface);
2733        if (err == OK) {
2734            mSurface = surface;
2735        }
2736    }
2737    return err;
2738}
2739
2740void MediaCodec::onInputBufferAvailable() {
2741    int32_t index;
2742    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2743        sp<AMessage> msg = mCallback->dup();
2744        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2745        msg->setInt32("index", index);
2746        msg->post();
2747    }
2748}
2749
2750void MediaCodec::onOutputBufferAvailable() {
2751    int32_t index;
2752    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2753        const sp<MediaCodecBuffer> &buffer =
2754            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2755        sp<AMessage> msg = mCallback->dup();
2756        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2757        msg->setInt32("index", index);
2758        msg->setSize("offset", buffer->offset());
2759        msg->setSize("size", buffer->size());
2760
2761        int64_t timeUs;
2762        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2763
2764        msg->setInt64("timeUs", timeUs);
2765
2766        int32_t omxFlags;
2767        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2768
2769        uint32_t flags = 0;
2770        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2771            flags |= BUFFER_FLAG_SYNCFRAME;
2772        }
2773        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2774            flags |= BUFFER_FLAG_CODECCONFIG;
2775        }
2776        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2777            flags |= BUFFER_FLAG_EOS;
2778        }
2779
2780        msg->setInt32("flags", flags);
2781
2782        msg->post();
2783    }
2784}
2785
2786void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2787    if (mCallback != NULL) {
2788        sp<AMessage> msg = mCallback->dup();
2789        msg->setInt32("callbackID", CB_ERROR);
2790        msg->setInt32("err", err);
2791        msg->setInt32("actionCode", actionCode);
2792
2793        if (detail != NULL) {
2794            msg->setString("detail", detail);
2795        }
2796
2797        msg->post();
2798    }
2799}
2800
2801void MediaCodec::onOutputFormatChanged() {
2802    if (mCallback != NULL) {
2803        sp<AMessage> msg = mCallback->dup();
2804        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2805        msg->setMessage("format", mOutputFormat);
2806        msg->post();
2807    }
2808}
2809
2810
2811void MediaCodec::postActivityNotificationIfPossible() {
2812    if (mActivityNotify == NULL) {
2813        return;
2814    }
2815
2816    bool isErrorOrOutputChanged =
2817            (mFlags & (kFlagStickyError
2818                    | kFlagOutputBuffersChanged
2819                    | kFlagOutputFormatChanged));
2820
2821    if (isErrorOrOutputChanged
2822            || !mAvailPortBuffers[kPortIndexInput].empty()
2823            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2824        mActivityNotify->setInt32("input-buffers",
2825                mAvailPortBuffers[kPortIndexInput].size());
2826
2827        if (isErrorOrOutputChanged) {
2828            // we want consumer to dequeue as many times as it can
2829            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2830        } else {
2831            mActivityNotify->setInt32("output-buffers",
2832                    mAvailPortBuffers[kPortIndexOutput].size());
2833        }
2834        mActivityNotify->post();
2835        mActivityNotify.clear();
2836    }
2837}
2838
2839status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2840    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2841    msg->setMessage("params", params);
2842
2843    sp<AMessage> response;
2844    return PostAndAwaitResponse(msg, &response);
2845}
2846
2847status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2848    mCodec->signalSetParameters(params);
2849
2850    return OK;
2851}
2852
2853status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2854        const sp<MediaCodecBuffer> &buffer) {
2855    AString mime;
2856    CHECK(mOutputFormat->findString("mime", &mime));
2857
2858    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2859        // Codec specific data should be SPS and PPS in a single buffer,
2860        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2861        // We separate the two and put them into the output format
2862        // under the keys "csd-0" and "csd-1".
2863
2864        unsigned csdIndex = 0;
2865
2866        const uint8_t *data = buffer->data();
2867        size_t size = buffer->size();
2868
2869        const uint8_t *nalStart;
2870        size_t nalSize;
2871        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2872            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2873            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2874            memcpy(csd->data() + 4, nalStart, nalSize);
2875
2876            mOutputFormat->setBuffer(
2877                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2878
2879            ++csdIndex;
2880        }
2881
2882        if (csdIndex != 2) {
2883            return ERROR_MALFORMED;
2884        }
2885    } else {
2886        // For everything else we just stash the codec specific data into
2887        // the output format as a single piece of csd under "csd-0".
2888        sp<ABuffer> csd = new ABuffer(buffer->size());
2889        memcpy(csd->data(), buffer->data(), buffer->size());
2890        csd->setRange(0, buffer->size());
2891        mOutputFormat->setBuffer("csd-0", csd);
2892    }
2893
2894    return OK;
2895}
2896
2897void MediaCodec::updateBatteryStat() {
2898    if (!mIsVideo) {
2899        return;
2900    }
2901
2902    if (mState == CONFIGURED && !mBatteryStatNotified) {
2903        BatteryNotifier::getInstance().noteStartVideo(mUid);
2904        mBatteryStatNotified = true;
2905    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2906        BatteryNotifier::getInstance().noteStopVideo(mUid);
2907        mBatteryStatNotified = false;
2908    }
2909}
2910
2911}  // namespace android
2912