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