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 <utils/Log.h>
     20 
     21 #include <media/stagefright/MediaCodec.h>
     22 
     23 #include "include/SoftwareRenderer.h"
     24 
     25 #include <gui/SurfaceTextureClient.h>
     26 #include <media/ICrypto.h>
     27 #include <media/stagefright/foundation/ABuffer.h>
     28 #include <media/stagefright/foundation/ADebug.h>
     29 #include <media/stagefright/foundation/AMessage.h>
     30 #include <media/stagefright/foundation/AString.h>
     31 #include <media/stagefright/foundation/hexdump.h>
     32 #include <media/stagefright/ACodec.h>
     33 #include <media/stagefright/MediaErrors.h>
     34 #include <media/stagefright/MetaData.h>
     35 #include <media/stagefright/NativeWindowWrapper.h>
     36 
     37 namespace android {
     38 
     39 // static
     40 sp<MediaCodec> MediaCodec::CreateByType(
     41         const sp<ALooper> &looper, const char *mime, bool encoder) {
     42     sp<MediaCodec> codec = new MediaCodec(looper);
     43     if (codec->init(mime, true /* nameIsType */, encoder) != OK) {
     44         return NULL;
     45     }
     46 
     47     return codec;
     48 }
     49 
     50 // static
     51 sp<MediaCodec> MediaCodec::CreateByComponentName(
     52         const sp<ALooper> &looper, const char *name) {
     53     sp<MediaCodec> codec = new MediaCodec(looper);
     54     if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) {
     55         return NULL;
     56     }
     57 
     58     return codec;
     59 }
     60 
     61 MediaCodec::MediaCodec(const sp<ALooper> &looper)
     62     : mState(UNINITIALIZED),
     63       mLooper(looper),
     64       mCodec(new ACodec),
     65       mFlags(0),
     66       mSoftRenderer(NULL),
     67       mDequeueInputTimeoutGeneration(0),
     68       mDequeueInputReplyID(0),
     69       mDequeueOutputTimeoutGeneration(0),
     70       mDequeueOutputReplyID(0) {
     71 }
     72 
     73 MediaCodec::~MediaCodec() {
     74     CHECK_EQ(mState, UNINITIALIZED);
     75 }
     76 
     77 // static
     78 status_t MediaCodec::PostAndAwaitResponse(
     79         const sp<AMessage> &msg, sp<AMessage> *response) {
     80     status_t err = msg->postAndAwaitResponse(response);
     81 
     82     if (err != OK) {
     83         return err;
     84     }
     85 
     86     if (!(*response)->findInt32("err", &err)) {
     87         err = OK;
     88     }
     89 
     90     return err;
     91 }
     92 
     93 status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
     94     // Current video decoders do not return from OMX_FillThisBuffer
     95     // quickly, violating the OpenMAX specs, until that is remedied
     96     // we need to invest in an extra looper to free the main event
     97     // queue.
     98     bool needDedicatedLooper = false;
     99     if (nameIsType && !strncasecmp(name, "video/", 6)) {
    100         needDedicatedLooper = true;
    101     } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) {
    102         needDedicatedLooper = true;
    103     }
    104 
    105     if (needDedicatedLooper) {
    106         if (mCodecLooper == NULL) {
    107             mCodecLooper = new ALooper;
    108             mCodecLooper->setName("CodecLooper");
    109             mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
    110         }
    111 
    112         mCodecLooper->registerHandler(mCodec);
    113     } else {
    114         mLooper->registerHandler(mCodec);
    115     }
    116 
    117     mLooper->registerHandler(this);
    118 
    119     mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
    120 
    121     sp<AMessage> msg = new AMessage(kWhatInit, id());
    122     msg->setString("name", name);
    123     msg->setInt32("nameIsType", nameIsType);
    124 
    125     if (nameIsType) {
    126         msg->setInt32("encoder", encoder);
    127     }
    128 
    129     sp<AMessage> response;
    130     return PostAndAwaitResponse(msg, &response);
    131 }
    132 
    133 status_t MediaCodec::configure(
    134         const sp<AMessage> &format,
    135         const sp<SurfaceTextureClient> &nativeWindow,
    136         const sp<ICrypto> &crypto,
    137         uint32_t flags) {
    138     sp<AMessage> msg = new AMessage(kWhatConfigure, id());
    139 
    140     msg->setMessage("format", format);
    141     msg->setInt32("flags", flags);
    142 
    143     if (nativeWindow != NULL) {
    144         msg->setObject(
    145                 "native-window",
    146                 new NativeWindowWrapper(nativeWindow));
    147     }
    148 
    149     if (crypto != NULL) {
    150         msg->setPointer("crypto", crypto.get());
    151     }
    152 
    153     sp<AMessage> response;
    154     return PostAndAwaitResponse(msg, &response);
    155 }
    156 
    157 status_t MediaCodec::start() {
    158     sp<AMessage> msg = new AMessage(kWhatStart, id());
    159 
    160     sp<AMessage> response;
    161     return PostAndAwaitResponse(msg, &response);
    162 }
    163 
    164 status_t MediaCodec::stop() {
    165     sp<AMessage> msg = new AMessage(kWhatStop, id());
    166 
    167     sp<AMessage> response;
    168     return PostAndAwaitResponse(msg, &response);
    169 }
    170 
    171 status_t MediaCodec::release() {
    172     sp<AMessage> msg = new AMessage(kWhatRelease, id());
    173 
    174     sp<AMessage> response;
    175     return PostAndAwaitResponse(msg, &response);
    176 }
    177 
    178 status_t MediaCodec::queueInputBuffer(
    179         size_t index,
    180         size_t offset,
    181         size_t size,
    182         int64_t presentationTimeUs,
    183         uint32_t flags,
    184         AString *errorDetailMsg) {
    185     if (errorDetailMsg != NULL) {
    186         errorDetailMsg->clear();
    187     }
    188 
    189     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
    190     msg->setSize("index", index);
    191     msg->setSize("offset", offset);
    192     msg->setSize("size", size);
    193     msg->setInt64("timeUs", presentationTimeUs);
    194     msg->setInt32("flags", flags);
    195     msg->setPointer("errorDetailMsg", errorDetailMsg);
    196 
    197     sp<AMessage> response;
    198     return PostAndAwaitResponse(msg, &response);
    199 }
    200 
    201 status_t MediaCodec::queueSecureInputBuffer(
    202         size_t index,
    203         size_t offset,
    204         const CryptoPlugin::SubSample *subSamples,
    205         size_t numSubSamples,
    206         const uint8_t key[16],
    207         const uint8_t iv[16],
    208         CryptoPlugin::Mode mode,
    209         int64_t presentationTimeUs,
    210         uint32_t flags,
    211         AString *errorDetailMsg) {
    212     if (errorDetailMsg != NULL) {
    213         errorDetailMsg->clear();
    214     }
    215 
    216     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
    217     msg->setSize("index", index);
    218     msg->setSize("offset", offset);
    219     msg->setPointer("subSamples", (void *)subSamples);
    220     msg->setSize("numSubSamples", numSubSamples);
    221     msg->setPointer("key", (void *)key);
    222     msg->setPointer("iv", (void *)iv);
    223     msg->setInt32("mode", mode);
    224     msg->setInt64("timeUs", presentationTimeUs);
    225     msg->setInt32("flags", flags);
    226     msg->setPointer("errorDetailMsg", errorDetailMsg);
    227 
    228     sp<AMessage> response;
    229     status_t err = PostAndAwaitResponse(msg, &response);
    230 
    231     return err;
    232 }
    233 
    234 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
    235     sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
    236     msg->setInt64("timeoutUs", timeoutUs);
    237 
    238     sp<AMessage> response;
    239     status_t err;
    240     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
    241         return err;
    242     }
    243 
    244     CHECK(response->findSize("index", index));
    245 
    246     return OK;
    247 }
    248 
    249 status_t MediaCodec::dequeueOutputBuffer(
    250         size_t *index,
    251         size_t *offset,
    252         size_t *size,
    253         int64_t *presentationTimeUs,
    254         uint32_t *flags,
    255         int64_t timeoutUs) {
    256     sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
    257     msg->setInt64("timeoutUs", timeoutUs);
    258 
    259     sp<AMessage> response;
    260     status_t err;
    261     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
    262         return err;
    263     }
    264 
    265     CHECK(response->findSize("index", index));
    266     CHECK(response->findSize("offset", offset));
    267     CHECK(response->findSize("size", size));
    268     CHECK(response->findInt64("timeUs", presentationTimeUs));
    269     CHECK(response->findInt32("flags", (int32_t *)flags));
    270 
    271     return OK;
    272 }
    273 
    274 status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
    275     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
    276     msg->setSize("index", index);
    277     msg->setInt32("render", true);
    278 
    279     sp<AMessage> response;
    280     return PostAndAwaitResponse(msg, &response);
    281 }
    282 
    283 status_t MediaCodec::releaseOutputBuffer(size_t index) {
    284     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
    285     msg->setSize("index", index);
    286 
    287     sp<AMessage> response;
    288     return PostAndAwaitResponse(msg, &response);
    289 }
    290 
    291 status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
    292     sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
    293 
    294     sp<AMessage> response;
    295     status_t err;
    296     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
    297         return err;
    298     }
    299 
    300     CHECK(response->findMessage("format", format));
    301 
    302     return OK;
    303 }
    304 
    305 status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
    306     sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
    307     msg->setInt32("portIndex", kPortIndexInput);
    308     msg->setPointer("buffers", buffers);
    309 
    310     sp<AMessage> response;
    311     return PostAndAwaitResponse(msg, &response);
    312 }
    313 
    314 status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
    315     sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
    316     msg->setInt32("portIndex", kPortIndexOutput);
    317     msg->setPointer("buffers", buffers);
    318 
    319     sp<AMessage> response;
    320     return PostAndAwaitResponse(msg, &response);
    321 }
    322 
    323 status_t MediaCodec::flush() {
    324     sp<AMessage> msg = new AMessage(kWhatFlush, id());
    325 
    326     sp<AMessage> response;
    327     return PostAndAwaitResponse(msg, &response);
    328 }
    329 
    330 ////////////////////////////////////////////////////////////////////////////////
    331 
    332 void MediaCodec::cancelPendingDequeueOperations() {
    333     if (mFlags & kFlagDequeueInputPending) {
    334         sp<AMessage> response = new AMessage;
    335         response->setInt32("err", INVALID_OPERATION);
    336         response->postReply(mDequeueInputReplyID);
    337 
    338         ++mDequeueInputTimeoutGeneration;
    339         mDequeueInputReplyID = 0;
    340         mFlags &= ~kFlagDequeueInputPending;
    341     }
    342 
    343     if (mFlags & kFlagDequeueOutputPending) {
    344         sp<AMessage> response = new AMessage;
    345         response->setInt32("err", INVALID_OPERATION);
    346         response->postReply(mDequeueOutputReplyID);
    347 
    348         ++mDequeueOutputTimeoutGeneration;
    349         mDequeueOutputReplyID = 0;
    350         mFlags &= ~kFlagDequeueOutputPending;
    351     }
    352 }
    353 
    354 bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
    355     if (mState != STARTED
    356             || (mFlags & kFlagStickyError)
    357             || (newRequest && (mFlags & kFlagDequeueInputPending))) {
    358         sp<AMessage> response = new AMessage;
    359         response->setInt32("err", INVALID_OPERATION);
    360 
    361         response->postReply(replyID);
    362 
    363         return true;
    364     }
    365 
    366     ssize_t index = dequeuePortBuffer(kPortIndexInput);
    367 
    368     if (index < 0) {
    369         CHECK_EQ(index, -EAGAIN);
    370         return false;
    371     }
    372 
    373     sp<AMessage> response = new AMessage;
    374     response->setSize("index", index);
    375     response->postReply(replyID);
    376 
    377     return true;
    378 }
    379 
    380 bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
    381     sp<AMessage> response = new AMessage;
    382 
    383     if (mState != STARTED
    384             || (mFlags & kFlagStickyError)
    385             || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
    386         response->setInt32("err", INVALID_OPERATION);
    387     } else if (mFlags & kFlagOutputBuffersChanged) {
    388         response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
    389         mFlags &= ~kFlagOutputBuffersChanged;
    390     } else if (mFlags & kFlagOutputFormatChanged) {
    391         response->setInt32("err", INFO_FORMAT_CHANGED);
    392         mFlags &= ~kFlagOutputFormatChanged;
    393     } else {
    394         ssize_t index = dequeuePortBuffer(kPortIndexOutput);
    395 
    396         if (index < 0) {
    397             CHECK_EQ(index, -EAGAIN);
    398             return false;
    399         }
    400 
    401         const sp<ABuffer> &buffer =
    402             mPortBuffers[kPortIndexOutput].itemAt(index).mData;
    403 
    404         response->setSize("index", index);
    405         response->setSize("offset", buffer->offset());
    406         response->setSize("size", buffer->size());
    407 
    408         int64_t timeUs;
    409         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
    410 
    411         response->setInt64("timeUs", timeUs);
    412 
    413         int32_t omxFlags;
    414         CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
    415 
    416         uint32_t flags = 0;
    417         if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
    418             flags |= BUFFER_FLAG_SYNCFRAME;
    419         }
    420         if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    421             flags |= BUFFER_FLAG_CODECCONFIG;
    422         }
    423         if (omxFlags & OMX_BUFFERFLAG_EOS) {
    424             flags |= BUFFER_FLAG_EOS;
    425         }
    426 
    427         response->setInt32("flags", flags);
    428     }
    429 
    430     response->postReply(replyID);
    431 
    432     return true;
    433 }
    434 
    435 void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
    436     switch (msg->what()) {
    437         case kWhatCodecNotify:
    438         {
    439             int32_t what;
    440             CHECK(msg->findInt32("what", &what));
    441 
    442             switch (what) {
    443                 case ACodec::kWhatError:
    444                 {
    445                     int32_t omxError, internalError;
    446                     CHECK(msg->findInt32("omx-error", &omxError));
    447                     CHECK(msg->findInt32("err", &internalError));
    448 
    449                     ALOGE("Codec reported an error. "
    450                           "(omx error 0x%08x, internalError %d)",
    451                           omxError, internalError);
    452 
    453                     bool sendErrorReponse = true;
    454 
    455                     switch (mState) {
    456                         case INITIALIZING:
    457                         {
    458                             setState(UNINITIALIZED);
    459                             break;
    460                         }
    461 
    462                         case CONFIGURING:
    463                         {
    464                             setState(INITIALIZED);
    465                             break;
    466                         }
    467 
    468                         case STARTING:
    469                         {
    470                             setState(CONFIGURED);
    471                             break;
    472                         }
    473 
    474                         case STOPPING:
    475                         case RELEASING:
    476                         {
    477                             // Ignore the error, assuming we'll still get
    478                             // the shutdown complete notification.
    479 
    480                             sendErrorReponse = false;
    481                             break;
    482                         }
    483 
    484                         case FLUSHING:
    485                         {
    486                             setState(STARTED);
    487                             break;
    488                         }
    489 
    490                         case STARTED:
    491                         {
    492                             sendErrorReponse = false;
    493 
    494                             mFlags |= kFlagStickyError;
    495 
    496                             cancelPendingDequeueOperations();
    497                             break;
    498                         }
    499 
    500                         default:
    501                         {
    502                             sendErrorReponse = false;
    503 
    504                             mFlags |= kFlagStickyError;
    505                             break;
    506                         }
    507                     }
    508 
    509                     if (sendErrorReponse) {
    510                         sp<AMessage> response = new AMessage;
    511                         response->setInt32("err", UNKNOWN_ERROR);
    512 
    513                         response->postReply(mReplyID);
    514                     }
    515                     break;
    516                 }
    517 
    518                 case ACodec::kWhatComponentAllocated:
    519                 {
    520                     CHECK_EQ(mState, INITIALIZING);
    521                     setState(INITIALIZED);
    522 
    523                     AString componentName;
    524                     CHECK(msg->findString("componentName", &componentName));
    525 
    526                     if (componentName.startsWith("OMX.google.")) {
    527                         mFlags |= kFlagIsSoftwareCodec;
    528                     } else {
    529                         mFlags &= ~kFlagIsSoftwareCodec;
    530                     }
    531 
    532                     if (componentName.endsWith(".secure")) {
    533                         mFlags |= kFlagIsSecure;
    534                     } else {
    535                         mFlags &= ~kFlagIsSecure;
    536                     }
    537 
    538                     (new AMessage)->postReply(mReplyID);
    539                     break;
    540                 }
    541 
    542                 case ACodec::kWhatComponentConfigured:
    543                 {
    544                     CHECK_EQ(mState, CONFIGURING);
    545                     setState(CONFIGURED);
    546 
    547                     (new AMessage)->postReply(mReplyID);
    548                     break;
    549                 }
    550 
    551                 case ACodec::kWhatBuffersAllocated:
    552                 {
    553                     int32_t portIndex;
    554                     CHECK(msg->findInt32("portIndex", &portIndex));
    555 
    556                     ALOGV("%s buffers allocated",
    557                           portIndex == kPortIndexInput ? "input" : "output");
    558 
    559                     CHECK(portIndex == kPortIndexInput
    560                             || portIndex == kPortIndexOutput);
    561 
    562                     mPortBuffers[portIndex].clear();
    563 
    564                     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
    565 
    566                     sp<RefBase> obj;
    567                     CHECK(msg->findObject("portDesc", &obj));
    568 
    569                     sp<ACodec::PortDescription> portDesc =
    570                         static_cast<ACodec::PortDescription *>(obj.get());
    571 
    572                     size_t numBuffers = portDesc->countBuffers();
    573 
    574                     for (size_t i = 0; i < numBuffers; ++i) {
    575                         BufferInfo info;
    576                         info.mBufferID = portDesc->bufferIDAt(i);
    577                         info.mOwnedByClient = false;
    578                         info.mData = portDesc->bufferAt(i);
    579 
    580                         if (portIndex == kPortIndexInput && mCrypto != NULL) {
    581                             info.mEncryptedData =
    582                                 new ABuffer(info.mData->capacity());
    583                         }
    584 
    585                         buffers->push_back(info);
    586                     }
    587 
    588                     if (portIndex == kPortIndexOutput) {
    589                         if (mState == STARTING) {
    590                             // We're always allocating output buffers after
    591                             // allocating input buffers, so this is a good
    592                             // indication that now all buffers are allocated.
    593                             setState(STARTED);
    594                             (new AMessage)->postReply(mReplyID);
    595                         } else {
    596                             mFlags |= kFlagOutputBuffersChanged;
    597                         }
    598                     }
    599                     break;
    600                 }
    601 
    602                 case ACodec::kWhatOutputFormatChanged:
    603                 {
    604                     ALOGV("codec output format changed");
    605 
    606                     if ((mFlags & kFlagIsSoftwareCodec)
    607                             && mNativeWindow != NULL) {
    608                         AString mime;
    609                         CHECK(msg->findString("mime", &mime));
    610 
    611                         if (!strncasecmp("video/", mime.c_str(), 6)) {
    612                             delete mSoftRenderer;
    613                             mSoftRenderer = NULL;
    614 
    615                             int32_t width, height;
    616                             CHECK(msg->findInt32("width", &width));
    617                             CHECK(msg->findInt32("height", &height));
    618 
    619                             int32_t colorFormat;
    620                             CHECK(msg->findInt32(
    621                                         "color-format", &colorFormat));
    622 
    623                             sp<MetaData> meta = new MetaData;
    624                             meta->setInt32(kKeyWidth, width);
    625                             meta->setInt32(kKeyHeight, height);
    626                             meta->setInt32(kKeyColorFormat, colorFormat);
    627 
    628                             mSoftRenderer =
    629                                 new SoftwareRenderer(mNativeWindow, meta);
    630                         }
    631                     }
    632 
    633                     mOutputFormat = msg;
    634                     mFlags |= kFlagOutputFormatChanged;
    635                     break;
    636                 }
    637 
    638                 case ACodec::kWhatFillThisBuffer:
    639                 {
    640                     /* size_t index = */updateBuffers(kPortIndexInput, msg);
    641 
    642                     if (mState == FLUSHING
    643                             || mState == STOPPING
    644                             || mState == RELEASING) {
    645                         returnBuffersToCodecOnPort(kPortIndexInput);
    646                         break;
    647                     }
    648 
    649                     if (!mCSD.empty()) {
    650                         ssize_t index = dequeuePortBuffer(kPortIndexInput);
    651                         CHECK_GE(index, 0);
    652 
    653                         // If codec specific data had been specified as
    654                         // part of the format in the call to configure and
    655                         // if there's more csd left, we submit it here
    656                         // clients only get access to input buffers once
    657                         // this data has been exhausted.
    658 
    659                         status_t err = queueCSDInputBuffer(index);
    660 
    661                         if (err != OK) {
    662                             ALOGE("queueCSDInputBuffer failed w/ error %d",
    663                                   err);
    664 
    665                             mFlags |= kFlagStickyError;
    666                             cancelPendingDequeueOperations();
    667                         }
    668                         break;
    669                     }
    670 
    671                     if (mFlags & kFlagDequeueInputPending) {
    672                         CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
    673 
    674                         ++mDequeueInputTimeoutGeneration;
    675                         mFlags &= ~kFlagDequeueInputPending;
    676                         mDequeueInputReplyID = 0;
    677                     }
    678                     break;
    679                 }
    680 
    681                 case ACodec::kWhatDrainThisBuffer:
    682                 {
    683                     /* size_t index = */updateBuffers(kPortIndexOutput, msg);
    684 
    685                     if (mState == FLUSHING
    686                             || mState == STOPPING
    687                             || mState == RELEASING) {
    688                         returnBuffersToCodecOnPort(kPortIndexOutput);
    689                         break;
    690                     }
    691 
    692                     sp<ABuffer> buffer;
    693                     CHECK(msg->findBuffer("buffer", &buffer));
    694 
    695                     int32_t omxFlags;
    696                     CHECK(msg->findInt32("flags", &omxFlags));
    697 
    698                     buffer->meta()->setInt32("omxFlags", omxFlags);
    699 
    700                     if (mFlags & kFlagDequeueOutputPending) {
    701                         CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
    702 
    703                         ++mDequeueOutputTimeoutGeneration;
    704                         mFlags &= ~kFlagDequeueOutputPending;
    705                         mDequeueOutputReplyID = 0;
    706                     }
    707                     break;
    708                 }
    709 
    710                 case ACodec::kWhatEOS:
    711                 {
    712                     // We already notify the client of this by using the
    713                     // corresponding flag in "onOutputBufferReady".
    714                     break;
    715                 }
    716 
    717                 case ACodec::kWhatShutdownCompleted:
    718                 {
    719                     if (mState == STOPPING) {
    720                         setState(INITIALIZED);
    721                     } else {
    722                         CHECK_EQ(mState, RELEASING);
    723                         setState(UNINITIALIZED);
    724                     }
    725 
    726                     (new AMessage)->postReply(mReplyID);
    727                     break;
    728                 }
    729 
    730                 case ACodec::kWhatFlushCompleted:
    731                 {
    732                     CHECK_EQ(mState, FLUSHING);
    733                     setState(STARTED);
    734 
    735                     mCodec->signalResume();
    736 
    737                     (new AMessage)->postReply(mReplyID);
    738                     break;
    739                 }
    740 
    741                 default:
    742                     TRESPASS();
    743             }
    744             break;
    745         }
    746 
    747         case kWhatInit:
    748         {
    749             uint32_t replyID;
    750             CHECK(msg->senderAwaitsResponse(&replyID));
    751 
    752             if (mState != UNINITIALIZED) {
    753                 sp<AMessage> response = new AMessage;
    754                 response->setInt32("err", INVALID_OPERATION);
    755 
    756                 response->postReply(replyID);
    757                 break;
    758             }
    759 
    760             mReplyID = replyID;
    761             setState(INITIALIZING);
    762 
    763             AString name;
    764             CHECK(msg->findString("name", &name));
    765 
    766             int32_t nameIsType;
    767             int32_t encoder = false;
    768             CHECK(msg->findInt32("nameIsType", &nameIsType));
    769             if (nameIsType) {
    770                 CHECK(msg->findInt32("encoder", &encoder));
    771             }
    772 
    773             sp<AMessage> format = new AMessage;
    774 
    775             if (nameIsType) {
    776                 format->setString("mime", name.c_str());
    777                 format->setInt32("encoder", encoder);
    778             } else {
    779                 format->setString("componentName", name.c_str());
    780             }
    781 
    782             mCodec->initiateAllocateComponent(format);
    783             break;
    784         }
    785 
    786         case kWhatConfigure:
    787         {
    788             uint32_t replyID;
    789             CHECK(msg->senderAwaitsResponse(&replyID));
    790 
    791             if (mState != INITIALIZED) {
    792                 sp<AMessage> response = new AMessage;
    793                 response->setInt32("err", INVALID_OPERATION);
    794 
    795                 response->postReply(replyID);
    796                 break;
    797             }
    798 
    799             sp<RefBase> obj;
    800             if (!msg->findObject("native-window", &obj)) {
    801                 obj.clear();
    802             }
    803 
    804             sp<AMessage> format;
    805             CHECK(msg->findMessage("format", &format));
    806 
    807             if (obj != NULL) {
    808                 format->setObject("native-window", obj);
    809 
    810                 status_t err = setNativeWindow(
    811                     static_cast<NativeWindowWrapper *>(obj.get())
    812                         ->getSurfaceTextureClient());
    813 
    814                 if (err != OK) {
    815                     sp<AMessage> response = new AMessage;
    816                     response->setInt32("err", err);
    817 
    818                     response->postReply(replyID);
    819                     break;
    820                 }
    821             } else {
    822                 setNativeWindow(NULL);
    823             }
    824 
    825             mReplyID = replyID;
    826             setState(CONFIGURING);
    827 
    828             void *crypto;
    829             if (!msg->findPointer("crypto", &crypto)) {
    830                 crypto = NULL;
    831             }
    832 
    833             mCrypto = static_cast<ICrypto *>(crypto);
    834 
    835             uint32_t flags;
    836             CHECK(msg->findInt32("flags", (int32_t *)&flags));
    837 
    838             if (flags & CONFIGURE_FLAG_ENCODE) {
    839                 format->setInt32("encoder", true);
    840             }
    841 
    842             extractCSD(format);
    843 
    844             mCodec->initiateConfigureComponent(format);
    845             break;
    846         }
    847 
    848         case kWhatStart:
    849         {
    850             uint32_t replyID;
    851             CHECK(msg->senderAwaitsResponse(&replyID));
    852 
    853             if (mState != CONFIGURED) {
    854                 sp<AMessage> response = new AMessage;
    855                 response->setInt32("err", INVALID_OPERATION);
    856 
    857                 response->postReply(replyID);
    858                 break;
    859             }
    860 
    861             mReplyID = replyID;
    862             setState(STARTING);
    863 
    864             mCodec->initiateStart();
    865             break;
    866         }
    867 
    868         case kWhatStop:
    869         {
    870             uint32_t replyID;
    871             CHECK(msg->senderAwaitsResponse(&replyID));
    872 
    873             if (mState != INITIALIZED
    874                     && mState != CONFIGURED && mState != STARTED) {
    875                 sp<AMessage> response = new AMessage;
    876                 response->setInt32("err", INVALID_OPERATION);
    877 
    878                 response->postReply(replyID);
    879                 break;
    880             }
    881 
    882             mReplyID = replyID;
    883             setState(STOPPING);
    884 
    885             mCodec->initiateShutdown(true /* keepComponentAllocated */);
    886             returnBuffersToCodec();
    887             break;
    888         }
    889 
    890         case kWhatRelease:
    891         {
    892             uint32_t replyID;
    893             CHECK(msg->senderAwaitsResponse(&replyID));
    894 
    895             if (mState != INITIALIZED
    896                     && mState != CONFIGURED && mState != STARTED) {
    897                 sp<AMessage> response = new AMessage;
    898                 response->setInt32("err", INVALID_OPERATION);
    899 
    900                 response->postReply(replyID);
    901                 break;
    902             }
    903 
    904             mReplyID = replyID;
    905             setState(RELEASING);
    906 
    907             mCodec->initiateShutdown();
    908             returnBuffersToCodec();
    909             break;
    910         }
    911 
    912         case kWhatDequeueInputBuffer:
    913         {
    914             uint32_t replyID;
    915             CHECK(msg->senderAwaitsResponse(&replyID));
    916 
    917             if (handleDequeueInputBuffer(replyID, true /* new request */)) {
    918                 break;
    919             }
    920 
    921             int64_t timeoutUs;
    922             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
    923 
    924             if (timeoutUs == 0ll) {
    925                 sp<AMessage> response = new AMessage;
    926                 response->setInt32("err", -EAGAIN);
    927                 response->postReply(replyID);
    928                 break;
    929             }
    930 
    931             mFlags |= kFlagDequeueInputPending;
    932             mDequeueInputReplyID = replyID;
    933 
    934             if (timeoutUs > 0ll) {
    935                 sp<AMessage> timeoutMsg =
    936                     new AMessage(kWhatDequeueInputTimedOut, id());
    937                 timeoutMsg->setInt32(
    938                         "generation", ++mDequeueInputTimeoutGeneration);
    939                 timeoutMsg->post(timeoutUs);
    940             }
    941             break;
    942         }
    943 
    944         case kWhatDequeueInputTimedOut:
    945         {
    946             int32_t generation;
    947             CHECK(msg->findInt32("generation", &generation));
    948 
    949             if (generation != mDequeueInputTimeoutGeneration) {
    950                 // Obsolete
    951                 break;
    952             }
    953 
    954             CHECK(mFlags & kFlagDequeueInputPending);
    955 
    956             sp<AMessage> response = new AMessage;
    957             response->setInt32("err", -EAGAIN);
    958             response->postReply(mDequeueInputReplyID);
    959 
    960             mFlags &= ~kFlagDequeueInputPending;
    961             mDequeueInputReplyID = 0;
    962             break;
    963         }
    964 
    965         case kWhatQueueInputBuffer:
    966         {
    967             uint32_t replyID;
    968             CHECK(msg->senderAwaitsResponse(&replyID));
    969 
    970             if (mState != STARTED || (mFlags & kFlagStickyError)) {
    971                 sp<AMessage> response = new AMessage;
    972                 response->setInt32("err", INVALID_OPERATION);
    973 
    974                 response->postReply(replyID);
    975                 break;
    976             }
    977 
    978             status_t err = onQueueInputBuffer(msg);
    979 
    980             sp<AMessage> response = new AMessage;
    981             response->setInt32("err", err);
    982             response->postReply(replyID);
    983             break;
    984         }
    985 
    986         case kWhatDequeueOutputBuffer:
    987         {
    988             uint32_t replyID;
    989             CHECK(msg->senderAwaitsResponse(&replyID));
    990 
    991             if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
    992                 break;
    993             }
    994 
    995             int64_t timeoutUs;
    996             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
    997 
    998             if (timeoutUs == 0ll) {
    999                 sp<AMessage> response = new AMessage;
   1000                 response->setInt32("err", -EAGAIN);
   1001                 response->postReply(replyID);
   1002                 break;
   1003             }
   1004 
   1005             mFlags |= kFlagDequeueOutputPending;
   1006             mDequeueOutputReplyID = replyID;
   1007 
   1008             if (timeoutUs > 0ll) {
   1009                 sp<AMessage> timeoutMsg =
   1010                     new AMessage(kWhatDequeueOutputTimedOut, id());
   1011                 timeoutMsg->setInt32(
   1012                         "generation", ++mDequeueOutputTimeoutGeneration);
   1013                 timeoutMsg->post(timeoutUs);
   1014             }
   1015             break;
   1016         }
   1017 
   1018         case kWhatDequeueOutputTimedOut:
   1019         {
   1020             int32_t generation;
   1021             CHECK(msg->findInt32("generation", &generation));
   1022 
   1023             if (generation != mDequeueOutputTimeoutGeneration) {
   1024                 // Obsolete
   1025                 break;
   1026             }
   1027 
   1028             CHECK(mFlags & kFlagDequeueOutputPending);
   1029 
   1030             sp<AMessage> response = new AMessage;
   1031             response->setInt32("err", -EAGAIN);
   1032             response->postReply(mDequeueOutputReplyID);
   1033 
   1034             mFlags &= ~kFlagDequeueOutputPending;
   1035             mDequeueOutputReplyID = 0;
   1036             break;
   1037         }
   1038 
   1039         case kWhatReleaseOutputBuffer:
   1040         {
   1041             uint32_t replyID;
   1042             CHECK(msg->senderAwaitsResponse(&replyID));
   1043 
   1044             if (mState != STARTED || (mFlags & kFlagStickyError)) {
   1045                 sp<AMessage> response = new AMessage;
   1046                 response->setInt32("err", INVALID_OPERATION);
   1047 
   1048                 response->postReply(replyID);
   1049                 break;
   1050             }
   1051 
   1052             status_t err = onReleaseOutputBuffer(msg);
   1053 
   1054             sp<AMessage> response = new AMessage;
   1055             response->setInt32("err", err);
   1056             response->postReply(replyID);
   1057             break;
   1058         }
   1059 
   1060         case kWhatGetBuffers:
   1061         {
   1062             uint32_t replyID;
   1063             CHECK(msg->senderAwaitsResponse(&replyID));
   1064 
   1065             if (mState != STARTED || (mFlags & kFlagStickyError)) {
   1066                 sp<AMessage> response = new AMessage;
   1067                 response->setInt32("err", INVALID_OPERATION);
   1068 
   1069                 response->postReply(replyID);
   1070                 break;
   1071             }
   1072 
   1073             int32_t portIndex;
   1074             CHECK(msg->findInt32("portIndex", &portIndex));
   1075 
   1076             Vector<sp<ABuffer> > *dstBuffers;
   1077             CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
   1078 
   1079             dstBuffers->clear();
   1080             const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
   1081 
   1082             for (size_t i = 0; i < srcBuffers.size(); ++i) {
   1083                 const BufferInfo &info = srcBuffers.itemAt(i);
   1084 
   1085                 dstBuffers->push_back(
   1086                         (portIndex == kPortIndexInput && mCrypto != NULL)
   1087                                 ? info.mEncryptedData : info.mData);
   1088             }
   1089 
   1090             (new AMessage)->postReply(replyID);
   1091             break;
   1092         }
   1093 
   1094         case kWhatFlush:
   1095         {
   1096             uint32_t replyID;
   1097             CHECK(msg->senderAwaitsResponse(&replyID));
   1098 
   1099             if (mState != STARTED || (mFlags & kFlagStickyError)) {
   1100                 sp<AMessage> response = new AMessage;
   1101                 response->setInt32("err", INVALID_OPERATION);
   1102 
   1103                 response->postReply(replyID);
   1104                 break;
   1105             }
   1106 
   1107             mReplyID = replyID;
   1108             setState(FLUSHING);
   1109 
   1110             mCodec->signalFlush();
   1111             returnBuffersToCodec();
   1112             break;
   1113         }
   1114 
   1115         case kWhatGetOutputFormat:
   1116         {
   1117             uint32_t replyID;
   1118             CHECK(msg->senderAwaitsResponse(&replyID));
   1119 
   1120             if ((mState != STARTED && mState != FLUSHING)
   1121                     || (mFlags & kFlagStickyError)) {
   1122                 sp<AMessage> response = new AMessage;
   1123                 response->setInt32("err", INVALID_OPERATION);
   1124 
   1125                 response->postReply(replyID);
   1126                 break;
   1127             }
   1128 
   1129             sp<AMessage> response = new AMessage;
   1130             response->setMessage("format", mOutputFormat);
   1131             response->postReply(replyID);
   1132             break;
   1133         }
   1134 
   1135         default:
   1136             TRESPASS();
   1137     }
   1138 }
   1139 
   1140 void MediaCodec::extractCSD(const sp<AMessage> &format) {
   1141     mCSD.clear();
   1142 
   1143     size_t i = 0;
   1144     for (;;) {
   1145         sp<ABuffer> csd;
   1146         if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
   1147             break;
   1148         }
   1149 
   1150         mCSD.push_back(csd);
   1151         ++i;
   1152     }
   1153 
   1154     ALOGV("Found %u pieces of codec specific data.", mCSD.size());
   1155 }
   1156 
   1157 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
   1158     CHECK(!mCSD.empty());
   1159 
   1160     BufferInfo *info =
   1161         &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex);
   1162 
   1163     sp<ABuffer> csd = *mCSD.begin();
   1164     mCSD.erase(mCSD.begin());
   1165 
   1166     const sp<ABuffer> &codecInputData =
   1167         (mCrypto != NULL) ? info->mEncryptedData : info->mData;
   1168 
   1169     if (csd->size() > codecInputData->capacity()) {
   1170         return -EINVAL;
   1171     }
   1172 
   1173     memcpy(codecInputData->data(), csd->data(), csd->size());
   1174 
   1175     AString errorDetailMsg;
   1176 
   1177     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
   1178     msg->setSize("index", bufferIndex);
   1179     msg->setSize("offset", 0);
   1180     msg->setSize("size", csd->size());
   1181     msg->setInt64("timeUs", 0ll);
   1182     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
   1183     msg->setPointer("errorDetailMsg", &errorDetailMsg);
   1184 
   1185     return onQueueInputBuffer(msg);
   1186 }
   1187 
   1188 void MediaCodec::setState(State newState) {
   1189     if (newState == INITIALIZED || newState == UNINITIALIZED) {
   1190         delete mSoftRenderer;
   1191         mSoftRenderer = NULL;
   1192 
   1193         mCrypto.clear();
   1194         setNativeWindow(NULL);
   1195 
   1196         mOutputFormat.clear();
   1197         mFlags &= ~kFlagOutputFormatChanged;
   1198         mFlags &= ~kFlagOutputBuffersChanged;
   1199         mFlags &= ~kFlagStickyError;
   1200     }
   1201 
   1202     mState = newState;
   1203 
   1204     cancelPendingDequeueOperations();
   1205 }
   1206 
   1207 void MediaCodec::returnBuffersToCodec() {
   1208     returnBuffersToCodecOnPort(kPortIndexInput);
   1209     returnBuffersToCodecOnPort(kPortIndexOutput);
   1210 }
   1211 
   1212 void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
   1213     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
   1214 
   1215     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
   1216 
   1217     for (size_t i = 0; i < buffers->size(); ++i) {
   1218         BufferInfo *info = &buffers->editItemAt(i);
   1219 
   1220         if (info->mNotify != NULL) {
   1221             sp<AMessage> msg = info->mNotify;
   1222             info->mNotify = NULL;
   1223             info->mOwnedByClient = false;
   1224 
   1225             if (portIndex == kPortIndexInput) {
   1226                 msg->setInt32("err", ERROR_END_OF_STREAM);
   1227             }
   1228             msg->post();
   1229         }
   1230     }
   1231 
   1232     mAvailPortBuffers[portIndex].clear();
   1233 }
   1234 
   1235 size_t MediaCodec::updateBuffers(
   1236         int32_t portIndex, const sp<AMessage> &msg) {
   1237     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
   1238 
   1239     void *bufferID;
   1240     CHECK(msg->findPointer("buffer-id", &bufferID));
   1241 
   1242     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
   1243 
   1244     for (size_t i = 0; i < buffers->size(); ++i) {
   1245         BufferInfo *info = &buffers->editItemAt(i);
   1246 
   1247         if (info->mBufferID == bufferID) {
   1248             CHECK(info->mNotify == NULL);
   1249             CHECK(msg->findMessage("reply", &info->mNotify));
   1250 
   1251             mAvailPortBuffers[portIndex].push_back(i);
   1252 
   1253             return i;
   1254         }
   1255     }
   1256 
   1257     TRESPASS();
   1258 
   1259     return 0;
   1260 }
   1261 
   1262 status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
   1263     size_t index;
   1264     size_t offset;
   1265     size_t size;
   1266     int64_t timeUs;
   1267     uint32_t flags;
   1268     CHECK(msg->findSize("index", &index));
   1269     CHECK(msg->findSize("offset", &offset));
   1270     CHECK(msg->findInt64("timeUs", &timeUs));
   1271     CHECK(msg->findInt32("flags", (int32_t *)&flags));
   1272 
   1273     const CryptoPlugin::SubSample *subSamples;
   1274     size_t numSubSamples;
   1275     const uint8_t *key;
   1276     const uint8_t *iv;
   1277     CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
   1278 
   1279     // We allow the simpler queueInputBuffer API to be used even in
   1280     // secure mode, by fabricating a single unencrypted subSample.
   1281     CryptoPlugin::SubSample ss;
   1282 
   1283     if (msg->findSize("size", &size)) {
   1284         if (mCrypto != NULL) {
   1285             ss.mNumBytesOfClearData = size;
   1286             ss.mNumBytesOfEncryptedData = 0;
   1287 
   1288             subSamples = &ss;
   1289             numSubSamples = 1;
   1290             key = NULL;
   1291             iv = NULL;
   1292         }
   1293     } else {
   1294         if (mCrypto == NULL) {
   1295             return -EINVAL;
   1296         }
   1297 
   1298         CHECK(msg->findPointer("subSamples", (void **)&subSamples));
   1299         CHECK(msg->findSize("numSubSamples", &numSubSamples));
   1300         CHECK(msg->findPointer("key", (void **)&key));
   1301         CHECK(msg->findPointer("iv", (void **)&iv));
   1302 
   1303         int32_t tmp;
   1304         CHECK(msg->findInt32("mode", &tmp));
   1305 
   1306         mode = (CryptoPlugin::Mode)tmp;
   1307 
   1308         size = 0;
   1309         for (size_t i = 0; i < numSubSamples; ++i) {
   1310             size += subSamples[i].mNumBytesOfClearData;
   1311             size += subSamples[i].mNumBytesOfEncryptedData;
   1312         }
   1313     }
   1314 
   1315     if (index >= mPortBuffers[kPortIndexInput].size()) {
   1316         return -ERANGE;
   1317     }
   1318 
   1319     BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
   1320 
   1321     if (info->mNotify == NULL || !info->mOwnedByClient) {
   1322         return -EACCES;
   1323     }
   1324 
   1325     if (offset + size > info->mData->capacity()) {
   1326         return -EINVAL;
   1327     }
   1328 
   1329     sp<AMessage> reply = info->mNotify;
   1330     info->mData->setRange(offset, size);
   1331     info->mData->meta()->setInt64("timeUs", timeUs);
   1332 
   1333     if (flags & BUFFER_FLAG_EOS) {
   1334         info->mData->meta()->setInt32("eos", true);
   1335     }
   1336 
   1337     if (flags & BUFFER_FLAG_CODECCONFIG) {
   1338         info->mData->meta()->setInt32("csd", true);
   1339     }
   1340 
   1341     if (mCrypto != NULL) {
   1342         if (size > info->mEncryptedData->capacity()) {
   1343             return -ERANGE;
   1344         }
   1345 
   1346         AString *errorDetailMsg;
   1347         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
   1348 
   1349         ssize_t result = mCrypto->decrypt(
   1350                 (mFlags & kFlagIsSecure) != 0,
   1351                 key,
   1352                 iv,
   1353                 mode,
   1354                 info->mEncryptedData->base() + offset,
   1355                 subSamples,
   1356                 numSubSamples,
   1357                 info->mData->base(),
   1358                 errorDetailMsg);
   1359 
   1360         if (result < 0) {
   1361             return result;
   1362         }
   1363 
   1364         info->mData->setRange(0, result);
   1365     }
   1366 
   1367     reply->setBuffer("buffer", info->mData);
   1368     reply->post();
   1369 
   1370     info->mNotify = NULL;
   1371     info->mOwnedByClient = false;
   1372 
   1373     return OK;
   1374 }
   1375 
   1376 status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
   1377     size_t index;
   1378     CHECK(msg->findSize("index", &index));
   1379 
   1380     int32_t render;
   1381     if (!msg->findInt32("render", &render)) {
   1382         render = 0;
   1383     }
   1384 
   1385     if (mState != STARTED) {
   1386         return -EINVAL;
   1387     }
   1388 
   1389     if (index >= mPortBuffers[kPortIndexOutput].size()) {
   1390         return -ERANGE;
   1391     }
   1392 
   1393     BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
   1394 
   1395     if (info->mNotify == NULL || !info->mOwnedByClient) {
   1396         return -EACCES;
   1397     }
   1398 
   1399     if (render) {
   1400         info->mNotify->setInt32("render", true);
   1401 
   1402         if (mSoftRenderer != NULL) {
   1403             mSoftRenderer->render(
   1404                     info->mData->data(), info->mData->size(), NULL);
   1405         }
   1406     }
   1407 
   1408     info->mNotify->post();
   1409     info->mNotify = NULL;
   1410     info->mOwnedByClient = false;
   1411 
   1412     return OK;
   1413 }
   1414 
   1415 ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
   1416     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
   1417 
   1418     List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
   1419 
   1420     if (availBuffers->empty()) {
   1421         return -EAGAIN;
   1422     }
   1423 
   1424     size_t index = *availBuffers->begin();
   1425     availBuffers->erase(availBuffers->begin());
   1426 
   1427     BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
   1428     CHECK(!info->mOwnedByClient);
   1429     info->mOwnedByClient = true;
   1430 
   1431     return index;
   1432 }
   1433 
   1434 status_t MediaCodec::setNativeWindow(
   1435         const sp<SurfaceTextureClient> &surfaceTextureClient) {
   1436     status_t err;
   1437 
   1438     if (mNativeWindow != NULL) {
   1439         err = native_window_api_disconnect(
   1440                 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
   1441 
   1442         if (err != OK) {
   1443             ALOGW("native_window_api_disconnect returned an error: %s (%d)",
   1444                     strerror(-err), err);
   1445         }
   1446 
   1447         mNativeWindow.clear();
   1448     }
   1449 
   1450     if (surfaceTextureClient != NULL) {
   1451         err = native_window_api_connect(
   1452                 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
   1453 
   1454         if (err != OK) {
   1455             ALOGE("native_window_api_connect returned an error: %s (%d)",
   1456                     strerror(-err), err);
   1457 
   1458             return err;
   1459         }
   1460 
   1461         mNativeWindow = surfaceTextureClient;
   1462     }
   1463 
   1464     return OK;
   1465 }
   1466 
   1467 }  // namespace android
   1468