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