Home | History | Annotate | Download | only in ndk
      1 /*
      2  * Copyright (C) 2014 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 #include <inttypes.h>
     18 
     19 //#define LOG_NDEBUG 0
     20 #define LOG_TAG "NdkMediaCodec"
     21 
     22 #include <media/NdkMediaCodec.h>
     23 #include <media/NdkMediaError.h>
     24 #include "NdkMediaCryptoPriv.h"
     25 #include "NdkMediaFormatPriv.h"
     26 
     27 #include <utils/Log.h>
     28 #include <utils/StrongPointer.h>
     29 #include <gui/Surface.h>
     30 
     31 #include <media/stagefright/foundation/ALooper.h>
     32 #include <media/stagefright/foundation/AMessage.h>
     33 
     34 #include <media/stagefright/PersistentSurface.h>
     35 #include <media/stagefright/MediaCodec.h>
     36 #include <media/stagefright/MediaErrors.h>
     37 #include <media/MediaCodecBuffer.h>
     38 #include <android/native_window.h>
     39 
     40 using namespace android;
     41 
     42 
     43 static media_status_t translate_error(status_t err) {
     44     if (err == OK) {
     45         return AMEDIA_OK;
     46     } else if (err == -EAGAIN) {
     47         return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
     48     }
     49     ALOGE("sf error code: %d", err);
     50     return AMEDIA_ERROR_UNKNOWN;
     51 }
     52 
     53 enum {
     54     kWhatActivityNotify,
     55     kWhatAsyncNotify,
     56     kWhatRequestActivityNotifications,
     57     kWhatStopActivityNotifications,
     58 };
     59 
     60 struct AMediaCodecPersistentSurface : public Surface {
     61     sp<PersistentSurface> mPersistentSurface;
     62     AMediaCodecPersistentSurface(
     63             const sp<IGraphicBufferProducer>& igbp,
     64             const sp<PersistentSurface>& ps)
     65             : Surface(igbp) {
     66         mPersistentSurface = ps;
     67     }
     68     virtual ~AMediaCodecPersistentSurface() {
     69         //mPersistentSurface ref will be let go off here
     70     }
     71 };
     72 
     73 class CodecHandler: public AHandler {
     74 private:
     75     AMediaCodec* mCodec;
     76 public:
     77     explicit CodecHandler(AMediaCodec *codec);
     78     virtual void onMessageReceived(const sp<AMessage> &msg);
     79 };
     80 
     81 typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
     82 
     83 struct AMediaCodec {
     84     sp<android::MediaCodec> mCodec;
     85     sp<ALooper> mLooper;
     86     sp<CodecHandler> mHandler;
     87     sp<AMessage> mActivityNotification;
     88     int32_t mGeneration;
     89     bool mRequestedActivityNotification;
     90     OnCodecEvent mCallback;
     91     void *mCallbackUserData;
     92 
     93     sp<AMessage> mAsyncNotify;
     94     mutable Mutex mAsyncCallbackLock;
     95     AMediaCodecOnAsyncNotifyCallback mAsyncCallback;
     96     void *mAsyncCallbackUserData;
     97 };
     98 
     99 CodecHandler::CodecHandler(AMediaCodec *codec) {
    100     mCodec = codec;
    101 }
    102 
    103 void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
    104 
    105     switch (msg->what()) {
    106         case kWhatRequestActivityNotifications:
    107         {
    108             if (mCodec->mRequestedActivityNotification) {
    109                 break;
    110             }
    111 
    112             mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
    113             mCodec->mRequestedActivityNotification = true;
    114             break;
    115         }
    116 
    117         case kWhatActivityNotify:
    118         {
    119             {
    120                 int32_t generation;
    121                 msg->findInt32("generation", &generation);
    122 
    123                 if (generation != mCodec->mGeneration) {
    124                     // stale
    125                     break;
    126                 }
    127 
    128                 mCodec->mRequestedActivityNotification = false;
    129             }
    130 
    131             if (mCodec->mCallback) {
    132                 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
    133             }
    134             break;
    135         }
    136 
    137         case kWhatAsyncNotify:
    138         {
    139              int32_t cbID;
    140              if (!msg->findInt32("callbackID", &cbID)) {
    141                  ALOGE("kWhatAsyncNotify: callbackID is expected.");
    142                  break;
    143              }
    144 
    145              ALOGV("kWhatAsyncNotify: cbID = %d", cbID);
    146 
    147              switch (cbID) {
    148                  case MediaCodec::CB_INPUT_AVAILABLE:
    149                  {
    150                      int32_t index;
    151                      if (!msg->findInt32("index", &index)) {
    152                          ALOGE("CB_INPUT_AVAILABLE: index is expected.");
    153                          break;
    154                      }
    155 
    156                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
    157                      if (mCodec->mAsyncCallbackUserData != NULL
    158                          || mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
    159                          mCodec->mAsyncCallback.onAsyncInputAvailable(
    160                                  mCodec,
    161                                  mCodec->mAsyncCallbackUserData,
    162                                  index);
    163                      }
    164 
    165                      break;
    166                  }
    167 
    168                  case MediaCodec::CB_OUTPUT_AVAILABLE:
    169                  {
    170                      int32_t index;
    171                      size_t offset;
    172                      size_t size;
    173                      int64_t timeUs;
    174                      int32_t flags;
    175 
    176                      if (!msg->findInt32("index", &index)) {
    177                          ALOGE("CB_OUTPUT_AVAILABLE: index is expected.");
    178                          break;
    179                      }
    180                      if (!msg->findSize("offset", &offset)) {
    181                          ALOGE("CB_OUTPUT_AVAILABLE: offset is expected.");
    182                          break;
    183                      }
    184                      if (!msg->findSize("size", &size)) {
    185                          ALOGE("CB_OUTPUT_AVAILABLE: size is expected.");
    186                          break;
    187                      }
    188                      if (!msg->findInt64("timeUs", &timeUs)) {
    189                          ALOGE("CB_OUTPUT_AVAILABLE: timeUs is expected.");
    190                          break;
    191                      }
    192                      if (!msg->findInt32("flags", &flags)) {
    193                          ALOGE("CB_OUTPUT_AVAILABLE: flags is expected.");
    194                          break;
    195                      }
    196 
    197                      AMediaCodecBufferInfo bufferInfo = {
    198                          (int32_t)offset,
    199                          (int32_t)size,
    200                          timeUs,
    201                          (uint32_t)flags};
    202 
    203                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
    204                      if (mCodec->mAsyncCallbackUserData != NULL
    205                          || mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
    206                          mCodec->mAsyncCallback.onAsyncOutputAvailable(
    207                                  mCodec,
    208                                  mCodec->mAsyncCallbackUserData,
    209                                  index,
    210                                  &bufferInfo);
    211                      }
    212 
    213                      break;
    214                  }
    215 
    216                  case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
    217                  {
    218                      sp<AMessage> format;
    219                      if (!msg->findMessage("format", &format)) {
    220                          ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
    221                          break;
    222                      }
    223 
    224                      AMediaFormat *aMediaFormat = AMediaFormat_fromMsg(&format);
    225 
    226                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
    227                      if (mCodec->mAsyncCallbackUserData != NULL
    228                          || mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
    229                          mCodec->mAsyncCallback.onAsyncFormatChanged(
    230                                  mCodec,
    231                                  mCodec->mAsyncCallbackUserData,
    232                                  aMediaFormat);
    233                      }
    234 
    235                      break;
    236                  }
    237 
    238                  case MediaCodec::CB_ERROR:
    239                  {
    240                      status_t err;
    241                      int32_t actionCode;
    242                      AString detail;
    243                      if (!msg->findInt32("err", &err)) {
    244                          ALOGE("CB_ERROR: err is expected.");
    245                          break;
    246                      }
    247                      if (!msg->findInt32("action", &actionCode)) {
    248                          ALOGE("CB_ERROR: action is expected.");
    249                          break;
    250                      }
    251                      msg->findString("detail", &detail);
    252                      ALOGE("Decoder reported error(0x%x), actionCode(%d), detail(%s)",
    253                            err, actionCode, detail.c_str());
    254 
    255                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
    256                      if (mCodec->mAsyncCallbackUserData != NULL
    257                          || mCodec->mAsyncCallback.onAsyncError != NULL) {
    258                          mCodec->mAsyncCallback.onAsyncError(
    259                                  mCodec,
    260                                  mCodec->mAsyncCallbackUserData,
    261                                  translate_error(err),
    262                                  actionCode,
    263                                  detail.c_str());
    264                      }
    265 
    266                      break;
    267                  }
    268 
    269                  default:
    270                  {
    271                      ALOGE("kWhatAsyncNotify: callbackID(%d) is unexpected.", cbID);
    272                      break;
    273                  }
    274              }
    275              break;
    276         }
    277 
    278         case kWhatStopActivityNotifications:
    279         {
    280             sp<AReplyToken> replyID;
    281             msg->senderAwaitsResponse(&replyID);
    282 
    283             mCodec->mGeneration++;
    284             mCodec->mRequestedActivityNotification = false;
    285 
    286             sp<AMessage> response = new AMessage;
    287             response->postReply(replyID);
    288             break;
    289         }
    290 
    291         default:
    292             ALOGE("shouldn't be here");
    293             break;
    294     }
    295 
    296 }
    297 
    298 
    299 static void requestActivityNotification(AMediaCodec *codec) {
    300     (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
    301 }
    302 
    303 extern "C" {
    304 
    305 static AMediaCodec * createAMediaCodec(const char *name, bool name_is_type, bool encoder) {
    306     AMediaCodec *mData = new AMediaCodec();
    307     mData->mLooper = new ALooper;
    308     mData->mLooper->setName("NDK MediaCodec_looper");
    309     size_t res = mData->mLooper->start(
    310             false,      // runOnCallingThread
    311             true,       // canCallJava XXX
    312             PRIORITY_AUDIO);
    313     if (res != OK) {
    314         ALOGE("Failed to start the looper");
    315         AMediaCodec_delete(mData);
    316         return NULL;
    317     }
    318     if (name_is_type) {
    319         mData->mCodec = android::MediaCodec::CreateByType(mData->mLooper, name, encoder);
    320     } else {
    321         mData->mCodec = android::MediaCodec::CreateByComponentName(mData->mLooper, name);
    322     }
    323     if (mData->mCodec == NULL) {  // failed to create codec
    324         AMediaCodec_delete(mData);
    325         return NULL;
    326     }
    327     mData->mHandler = new CodecHandler(mData);
    328     mData->mLooper->registerHandler(mData->mHandler);
    329     mData->mGeneration = 1;
    330     mData->mRequestedActivityNotification = false;
    331     mData->mCallback = NULL;
    332 
    333     mData->mAsyncCallback = {};
    334     mData->mAsyncCallbackUserData = NULL;
    335 
    336     return mData;
    337 }
    338 
    339 EXPORT
    340 AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
    341     return createAMediaCodec(name, false, false);
    342 }
    343 
    344 EXPORT
    345 AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
    346     return createAMediaCodec(mime_type, true, false);
    347 }
    348 
    349 EXPORT
    350 AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
    351     return createAMediaCodec(name, true, true);
    352 }
    353 
    354 EXPORT
    355 media_status_t AMediaCodec_delete(AMediaCodec *mData) {
    356     if (mData != NULL) {
    357         if (mData->mCodec != NULL) {
    358             mData->mCodec->release();
    359             mData->mCodec.clear();
    360         }
    361 
    362         if (mData->mLooper != NULL) {
    363             if (mData->mHandler != NULL) {
    364                 mData->mLooper->unregisterHandler(mData->mHandler->id());
    365             }
    366             mData->mLooper->stop();
    367             mData->mLooper.clear();
    368         }
    369         delete mData;
    370     }
    371     return AMEDIA_OK;
    372 }
    373 
    374 EXPORT
    375 media_status_t AMediaCodec_getName(
    376         AMediaCodec *mData,
    377         char** out_name) {
    378     if (out_name == NULL) {
    379         return AMEDIA_ERROR_INVALID_PARAMETER;
    380     }
    381 
    382     AString compName;
    383     status_t err = mData->mCodec->getName(&compName);
    384     if (err != OK) {
    385         return translate_error(err);
    386     }
    387     *out_name = strdup(compName.c_str());
    388     return AMEDIA_OK;
    389 }
    390 
    391 EXPORT
    392 void AMediaCodec_releaseName(
    393         AMediaCodec * /* mData */,
    394         char* name) {
    395     if (name != NULL) {
    396         free(name);
    397     }
    398 }
    399 
    400 EXPORT
    401 media_status_t AMediaCodec_configure(
    402         AMediaCodec *mData,
    403         const AMediaFormat* format,
    404         ANativeWindow* window,
    405         AMediaCrypto *crypto,
    406         uint32_t flags) {
    407     sp<AMessage> nativeFormat;
    408     AMediaFormat_getFormat(format, &nativeFormat);
    409     ALOGV("configure with format: %s", nativeFormat->debugString(0).c_str());
    410     sp<Surface> surface = NULL;
    411     if (window != NULL) {
    412         surface = (Surface*) window;
    413     }
    414 
    415     status_t err = mData->mCodec->configure(nativeFormat, surface,
    416             crypto ? crypto->mCrypto : NULL, flags);
    417     if (err != OK) {
    418         ALOGE("configure: err(%d), failed with format: %s",
    419               err, nativeFormat->debugString(0).c_str());
    420     }
    421     return translate_error(err);
    422 }
    423 
    424 EXPORT
    425 media_status_t AMediaCodec_setAsyncNotifyCallback(
    426         AMediaCodec *mData,
    427         AMediaCodecOnAsyncNotifyCallback callback,
    428         void *userdata) {
    429     if (mData->mAsyncNotify == NULL && userdata != NULL) {
    430         mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
    431         status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
    432         if (err != OK) {
    433             ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
    434             return translate_error(err);
    435         }
    436     }
    437 
    438     Mutex::Autolock _l(mData->mAsyncCallbackLock);
    439     mData->mAsyncCallback = callback;
    440     mData->mAsyncCallbackUserData = userdata;
    441 
    442     return AMEDIA_OK;
    443 }
    444 
    445 
    446 EXPORT
    447 media_status_t AMediaCodec_releaseCrypto(AMediaCodec *mData) {
    448     return translate_error(mData->mCodec->releaseCrypto());
    449 }
    450 
    451 EXPORT
    452 media_status_t AMediaCodec_start(AMediaCodec *mData) {
    453     status_t ret =  mData->mCodec->start();
    454     if (ret != OK) {
    455         return translate_error(ret);
    456     }
    457     mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
    458     mData->mActivityNotification->setInt32("generation", mData->mGeneration);
    459     requestActivityNotification(mData);
    460     return AMEDIA_OK;
    461 }
    462 
    463 EXPORT
    464 media_status_t AMediaCodec_stop(AMediaCodec *mData) {
    465     media_status_t ret = translate_error(mData->mCodec->stop());
    466 
    467     sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
    468     sp<AMessage> response;
    469     msg->postAndAwaitResponse(&response);
    470     mData->mActivityNotification.clear();
    471 
    472     return ret;
    473 }
    474 
    475 EXPORT
    476 media_status_t AMediaCodec_flush(AMediaCodec *mData) {
    477     return translate_error(mData->mCodec->flush());
    478 }
    479 
    480 EXPORT
    481 ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
    482     size_t idx;
    483     status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
    484     requestActivityNotification(mData);
    485     if (ret == OK) {
    486         return idx;
    487     }
    488     return translate_error(ret);
    489 }
    490 
    491 EXPORT
    492 uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
    493     if (mData->mAsyncNotify != NULL) {
    494         // Asynchronous mode
    495         sp<MediaCodecBuffer> abuf;
    496         if (mData->mCodec->getInputBuffer(idx, &abuf) != 0) {
    497             return NULL;
    498         }
    499 
    500         if (out_size != NULL) {
    501             *out_size = abuf->capacity();
    502         }
    503         return abuf->data();
    504     }
    505 
    506     android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
    507     if (mData->mCodec->getInputBuffers(&abufs) == 0) {
    508         size_t n = abufs.size();
    509         if (idx >= n) {
    510             ALOGE("buffer index %zu out of range", idx);
    511             return NULL;
    512         }
    513         if (abufs[idx] == NULL) {
    514             ALOGE("buffer index %zu is NULL", idx);
    515             return NULL;
    516         }
    517         if (out_size != NULL) {
    518             *out_size = abufs[idx]->capacity();
    519         }
    520         return abufs[idx]->data();
    521     }
    522     ALOGE("couldn't get input buffers");
    523     return NULL;
    524 }
    525 
    526 EXPORT
    527 uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
    528     if (mData->mAsyncNotify != NULL) {
    529         // Asynchronous mode
    530         sp<MediaCodecBuffer> abuf;
    531         if (mData->mCodec->getOutputBuffer(idx, &abuf) != 0) {
    532             return NULL;
    533         }
    534 
    535         if (out_size != NULL) {
    536             *out_size = abuf->capacity();
    537         }
    538         return abuf->data();
    539     }
    540 
    541     android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
    542     if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
    543         size_t n = abufs.size();
    544         if (idx >= n) {
    545             ALOGE("buffer index %zu out of range", idx);
    546             return NULL;
    547         }
    548         if (out_size != NULL) {
    549             *out_size = abufs[idx]->capacity();
    550         }
    551         return abufs[idx]->data();
    552     }
    553     ALOGE("couldn't get output buffers");
    554     return NULL;
    555 }
    556 
    557 EXPORT
    558 media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
    559         size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
    560 
    561     AString errorMsg;
    562     status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
    563     return translate_error(ret);
    564 }
    565 
    566 EXPORT
    567 ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
    568         AMediaCodecBufferInfo *info, int64_t timeoutUs) {
    569     size_t idx;
    570     size_t offset;
    571     size_t size;
    572     uint32_t flags;
    573     int64_t presentationTimeUs;
    574     status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
    575             &flags, timeoutUs);
    576     requestActivityNotification(mData);
    577     switch (ret) {
    578         case OK:
    579             info->offset = offset;
    580             info->size = size;
    581             info->flags = flags;
    582             info->presentationTimeUs = presentationTimeUs;
    583             return idx;
    584         case -EAGAIN:
    585             return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
    586         case android::INFO_FORMAT_CHANGED:
    587             return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
    588         case INFO_OUTPUT_BUFFERS_CHANGED:
    589             return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
    590         default:
    591             break;
    592     }
    593     return translate_error(ret);
    594 }
    595 
    596 EXPORT
    597 AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
    598     sp<AMessage> format;
    599     mData->mCodec->getOutputFormat(&format);
    600     return AMediaFormat_fromMsg(&format);
    601 }
    602 
    603 EXPORT
    604 AMediaFormat* AMediaCodec_getInputFormat(AMediaCodec *mData) {
    605     sp<AMessage> format;
    606     mData->mCodec->getInputFormat(&format);
    607     return AMediaFormat_fromMsg(&format);
    608 }
    609 
    610 EXPORT
    611 AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) {
    612     sp<AMessage> format;
    613     mData->mCodec->getOutputFormat(index, &format);
    614     return AMediaFormat_fromMsg(&format);
    615 }
    616 
    617 EXPORT
    618 media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
    619     if (render) {
    620         return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
    621     } else {
    622         return translate_error(mData->mCodec->releaseOutputBuffer(idx));
    623     }
    624 }
    625 
    626 EXPORT
    627 media_status_t AMediaCodec_releaseOutputBufferAtTime(
    628         AMediaCodec *mData, size_t idx, int64_t timestampNs) {
    629     ALOGV("render @ %" PRId64, timestampNs);
    630     return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
    631 }
    632 
    633 EXPORT
    634 media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
    635     sp<Surface> surface = NULL;
    636     if (window != NULL) {
    637         surface = (Surface*) window;
    638     }
    639     return translate_error(mData->mCodec->setSurface(surface));
    640 }
    641 
    642 EXPORT
    643 media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
    644     if (surface == NULL || mData == NULL) {
    645         return AMEDIA_ERROR_INVALID_PARAMETER;
    646     }
    647     *surface = NULL;
    648 
    649     sp<IGraphicBufferProducer> igbp = NULL;
    650     status_t err = mData->mCodec->createInputSurface(&igbp);
    651     if (err != NO_ERROR) {
    652         return translate_error(err);
    653     }
    654 
    655     *surface = new Surface(igbp);
    656     ANativeWindow_acquire(*surface);
    657     return AMEDIA_OK;
    658 }
    659 
    660 EXPORT
    661 media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
    662     if (surface == NULL) {
    663         return AMEDIA_ERROR_INVALID_PARAMETER;
    664     }
    665     *surface = NULL;
    666 
    667     sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
    668     if (ps == NULL) {
    669         return AMEDIA_ERROR_UNKNOWN;
    670     }
    671 
    672     sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
    673     if (igbp == NULL) {
    674         return AMEDIA_ERROR_UNKNOWN;
    675     }
    676 
    677     *surface = new AMediaCodecPersistentSurface(igbp, ps);
    678     ANativeWindow_acquire(*surface);
    679 
    680     return AMEDIA_OK;
    681 }
    682 
    683 EXPORT
    684 media_status_t AMediaCodec_setInputSurface(
    685         AMediaCodec *mData, ANativeWindow *surface) {
    686 
    687     if (surface == NULL || mData == NULL) {
    688         return AMEDIA_ERROR_INVALID_PARAMETER;
    689     }
    690 
    691     AMediaCodecPersistentSurface *aMediaPersistentSurface =
    692             static_cast<AMediaCodecPersistentSurface *>(surface);
    693     if (aMediaPersistentSurface->mPersistentSurface == NULL) {
    694         return AMEDIA_ERROR_INVALID_PARAMETER;
    695     }
    696 
    697     return translate_error(mData->mCodec->setInputSurface(
    698             aMediaPersistentSurface->mPersistentSurface));
    699 }
    700 
    701 EXPORT
    702 media_status_t AMediaCodec_setParameters(
    703         AMediaCodec *mData, const AMediaFormat* params) {
    704     if (params == NULL || mData == NULL) {
    705         return AMEDIA_ERROR_INVALID_PARAMETER;
    706     }
    707     sp<AMessage> nativeParams;
    708     AMediaFormat_getFormat(params, &nativeParams);
    709     ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
    710 
    711     return translate_error(mData->mCodec->setParameters(nativeParams));
    712 }
    713 
    714 EXPORT
    715 media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
    716 
    717     if (mData == NULL) {
    718         return AMEDIA_ERROR_INVALID_PARAMETER;
    719     }
    720 
    721     status_t err = mData->mCodec->signalEndOfInputStream();
    722     if (err == INVALID_OPERATION) {
    723         return AMEDIA_ERROR_INVALID_OPERATION;
    724     }
    725 
    726     return translate_error(err);
    727 
    728 }
    729 
    730 //EXPORT
    731 media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
    732         void *userdata) {
    733     mData->mCallback = callback;
    734     mData->mCallbackUserData = userdata;
    735     return AMEDIA_OK;
    736 }
    737 
    738 typedef struct AMediaCodecCryptoInfo {
    739         int numsubsamples;
    740         uint8_t key[16];
    741         uint8_t iv[16];
    742         cryptoinfo_mode_t mode;
    743         cryptoinfo_pattern_t pattern;
    744         size_t *clearbytes;
    745         size_t *encryptedbytes;
    746 } AMediaCodecCryptoInfo;
    747 
    748 EXPORT
    749 media_status_t AMediaCodec_queueSecureInputBuffer(
    750         AMediaCodec* codec,
    751         size_t idx,
    752         off_t offset,
    753         AMediaCodecCryptoInfo* crypto,
    754         uint64_t time,
    755         uint32_t flags) {
    756 
    757     CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
    758     for (int i = 0; i < crypto->numsubsamples; i++) {
    759         subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
    760         subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
    761     }
    762 
    763     CryptoPlugin::Pattern pattern;
    764     pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
    765     pattern.mSkipBlocks = crypto->pattern.skipBlocks;
    766 
    767     AString errormsg;
    768     status_t err  = codec->mCodec->queueSecureInputBuffer(idx,
    769             offset,
    770             subSamples,
    771             crypto->numsubsamples,
    772             crypto->key,
    773             crypto->iv,
    774             (CryptoPlugin::Mode)crypto->mode,
    775             pattern,
    776             time,
    777             flags,
    778             &errormsg);
    779     if (err != 0) {
    780         ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
    781     }
    782     delete [] subSamples;
    783     return translate_error(err);
    784 }
    785 
    786 EXPORT
    787 bool AMediaCodecActionCode_isRecoverable(int32_t actionCode) {
    788     return (actionCode == ACTION_CODE_RECOVERABLE);
    789 }
    790 
    791 EXPORT
    792 bool AMediaCodecActionCode_isTransient(int32_t actionCode) {
    793     return (actionCode == ACTION_CODE_TRANSIENT);
    794 }
    795 
    796 
    797 EXPORT
    798 void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
    799         cryptoinfo_pattern_t *pattern) {
    800     info->pattern.encryptBlocks = pattern->encryptBlocks;
    801     info->pattern.skipBlocks = pattern->skipBlocks;
    802 }
    803 
    804 EXPORT
    805 AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
    806         int numsubsamples,
    807         uint8_t key[16],
    808         uint8_t iv[16],
    809         cryptoinfo_mode_t mode,
    810         size_t *clearbytes,
    811         size_t *encryptedbytes) {
    812 
    813     // size needed to store all the crypto data
    814     size_t cryptosize = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
    815     AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
    816     if (!ret) {
    817         ALOGE("couldn't allocate %zu bytes", cryptosize);
    818         return NULL;
    819     }
    820     ret->numsubsamples = numsubsamples;
    821     memcpy(ret->key, key, 16);
    822     memcpy(ret->iv, iv, 16);
    823     ret->mode = mode;
    824     ret->pattern.encryptBlocks = 0;
    825     ret->pattern.skipBlocks = 0;
    826 
    827     // clearbytes and encryptedbytes point at the actual data, which follows
    828     ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
    829     ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
    830 
    831     memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
    832     memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
    833 
    834     return ret;
    835 }
    836 
    837 
    838 EXPORT
    839 media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
    840     free(info);
    841     return AMEDIA_OK;
    842 }
    843 
    844 EXPORT
    845 size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
    846     return ci->numsubsamples;
    847 }
    848 
    849 EXPORT
    850 media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
    851     if (!ci) {
    852         return AMEDIA_ERROR_INVALID_OBJECT;
    853     }
    854     if (!dst) {
    855         return AMEDIA_ERROR_INVALID_PARAMETER;
    856     }
    857     memcpy(dst, ci->key, 16);
    858     return AMEDIA_OK;
    859 }
    860 
    861 EXPORT
    862 media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
    863     if (!ci) {
    864         return AMEDIA_ERROR_INVALID_OBJECT;
    865     }
    866     if (!dst) {
    867         return AMEDIA_ERROR_INVALID_PARAMETER;
    868     }
    869     memcpy(dst, ci->iv, 16);
    870     return AMEDIA_OK;
    871 }
    872 
    873 EXPORT
    874 cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
    875     if (!ci) {
    876         return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
    877     }
    878     return ci->mode;
    879 }
    880 
    881 EXPORT
    882 media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
    883     if (!ci) {
    884         return AMEDIA_ERROR_INVALID_OBJECT;
    885     }
    886     if (!dst) {
    887         return AMEDIA_ERROR_INVALID_PARAMETER;
    888     }
    889     memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
    890     return AMEDIA_OK;
    891 }
    892 
    893 EXPORT
    894 media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
    895     if (!ci) {
    896         return AMEDIA_ERROR_INVALID_OBJECT;
    897     }
    898     if (!dst) {
    899         return AMEDIA_ERROR_INVALID_PARAMETER;
    900     }
    901     memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
    902     return AMEDIA_OK;
    903 }
    904 
    905 } // extern "C"
    906 
    907