Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2010 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 "ACodec"
     19 
     20 #include <media/stagefright/ACodec.h>
     21 
     22 #include <binder/MemoryDealer.h>
     23 
     24 #include <media/stagefright/foundation/hexdump.h>
     25 #include <media/stagefright/foundation/ABuffer.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/AMessage.h>
     28 
     29 #include <media/stagefright/BufferProducerWrapper.h>
     30 #include <media/stagefright/MediaCodecList.h>
     31 #include <media/stagefright/MediaDefs.h>
     32 #include <media/stagefright/NativeWindowWrapper.h>
     33 #include <media/stagefright/OMXClient.h>
     34 #include <media/stagefright/OMXCodec.h>
     35 
     36 #include <media/hardware/HardwareAPI.h>
     37 
     38 #include <OMX_Component.h>
     39 
     40 #include "include/avc_utils.h"
     41 
     42 namespace android {
     43 
     44 template<class T>
     45 static void InitOMXParams(T *params) {
     46     params->nSize = sizeof(T);
     47     params->nVersion.s.nVersionMajor = 1;
     48     params->nVersion.s.nVersionMinor = 0;
     49     params->nVersion.s.nRevision = 0;
     50     params->nVersion.s.nStep = 0;
     51 }
     52 
     53 struct CodecObserver : public BnOMXObserver {
     54     CodecObserver() {}
     55 
     56     void setNotificationMessage(const sp<AMessage> &msg) {
     57         mNotify = msg;
     58     }
     59 
     60     // from IOMXObserver
     61     virtual void onMessage(const omx_message &omx_msg) {
     62         sp<AMessage> msg = mNotify->dup();
     63 
     64         msg->setInt32("type", omx_msg.type);
     65         msg->setPointer("node", omx_msg.node);
     66 
     67         switch (omx_msg.type) {
     68             case omx_message::EVENT:
     69             {
     70                 msg->setInt32("event", omx_msg.u.event_data.event);
     71                 msg->setInt32("data1", omx_msg.u.event_data.data1);
     72                 msg->setInt32("data2", omx_msg.u.event_data.data2);
     73                 break;
     74             }
     75 
     76             case omx_message::EMPTY_BUFFER_DONE:
     77             {
     78                 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
     79                 break;
     80             }
     81 
     82             case omx_message::FILL_BUFFER_DONE:
     83             {
     84                 msg->setPointer(
     85                         "buffer", omx_msg.u.extended_buffer_data.buffer);
     86                 msg->setInt32(
     87                         "range_offset",
     88                         omx_msg.u.extended_buffer_data.range_offset);
     89                 msg->setInt32(
     90                         "range_length",
     91                         omx_msg.u.extended_buffer_data.range_length);
     92                 msg->setInt32(
     93                         "flags",
     94                         omx_msg.u.extended_buffer_data.flags);
     95                 msg->setInt64(
     96                         "timestamp",
     97                         omx_msg.u.extended_buffer_data.timestamp);
     98                 msg->setPointer(
     99                         "platform_private",
    100                         omx_msg.u.extended_buffer_data.platform_private);
    101                 msg->setPointer(
    102                         "data_ptr",
    103                         omx_msg.u.extended_buffer_data.data_ptr);
    104                 break;
    105             }
    106 
    107             default:
    108                 TRESPASS();
    109                 break;
    110         }
    111 
    112         msg->post();
    113     }
    114 
    115 protected:
    116     virtual ~CodecObserver() {}
    117 
    118 private:
    119     sp<AMessage> mNotify;
    120 
    121     DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
    122 };
    123 
    124 ////////////////////////////////////////////////////////////////////////////////
    125 
    126 struct ACodec::BaseState : public AState {
    127     BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
    128 
    129 protected:
    130     enum PortMode {
    131         KEEP_BUFFERS,
    132         RESUBMIT_BUFFERS,
    133         FREE_BUFFERS,
    134     };
    135 
    136     ACodec *mCodec;
    137 
    138     virtual PortMode getPortMode(OMX_U32 portIndex);
    139 
    140     virtual bool onMessageReceived(const sp<AMessage> &msg);
    141 
    142     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    143 
    144     virtual void onOutputBufferDrained(const sp<AMessage> &msg);
    145     virtual void onInputBufferFilled(const sp<AMessage> &msg);
    146 
    147     void postFillThisBuffer(BufferInfo *info);
    148 
    149 private:
    150     bool onOMXMessage(const sp<AMessage> &msg);
    151 
    152     bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
    153 
    154     bool onOMXFillBufferDone(
    155             IOMX::buffer_id bufferID,
    156             size_t rangeOffset, size_t rangeLength,
    157             OMX_U32 flags,
    158             int64_t timeUs,
    159             void *platformPrivate,
    160             void *dataPtr);
    161 
    162     void getMoreInputDataIfPossible();
    163 
    164     DISALLOW_EVIL_CONSTRUCTORS(BaseState);
    165 };
    166 
    167 ////////////////////////////////////////////////////////////////////////////////
    168 
    169 struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
    170     DeathNotifier(const sp<AMessage> &notify)
    171         : mNotify(notify) {
    172     }
    173 
    174     virtual void binderDied(const wp<IBinder> &) {
    175         mNotify->post();
    176     }
    177 
    178 protected:
    179     virtual ~DeathNotifier() {}
    180 
    181 private:
    182     sp<AMessage> mNotify;
    183 
    184     DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
    185 };
    186 
    187 struct ACodec::UninitializedState : public ACodec::BaseState {
    188     UninitializedState(ACodec *codec);
    189 
    190 protected:
    191     virtual bool onMessageReceived(const sp<AMessage> &msg);
    192     virtual void stateEntered();
    193 
    194 private:
    195     void onSetup(const sp<AMessage> &msg);
    196     bool onAllocateComponent(const sp<AMessage> &msg);
    197 
    198     sp<DeathNotifier> mDeathNotifier;
    199 
    200     DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
    201 };
    202 
    203 ////////////////////////////////////////////////////////////////////////////////
    204 
    205 struct ACodec::LoadedState : public ACodec::BaseState {
    206     LoadedState(ACodec *codec);
    207 
    208 protected:
    209     virtual bool onMessageReceived(const sp<AMessage> &msg);
    210     virtual void stateEntered();
    211 
    212 private:
    213     friend struct ACodec::UninitializedState;
    214 
    215     bool onConfigureComponent(const sp<AMessage> &msg);
    216     void onCreateInputSurface(const sp<AMessage> &msg);
    217     void onStart();
    218     void onShutdown(bool keepComponentAllocated);
    219 
    220     DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
    221 };
    222 
    223 ////////////////////////////////////////////////////////////////////////////////
    224 
    225 struct ACodec::LoadedToIdleState : public ACodec::BaseState {
    226     LoadedToIdleState(ACodec *codec);
    227 
    228 protected:
    229     virtual bool onMessageReceived(const sp<AMessage> &msg);
    230     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    231     virtual void stateEntered();
    232 
    233 private:
    234     status_t allocateBuffers();
    235 
    236     DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
    237 };
    238 
    239 ////////////////////////////////////////////////////////////////////////////////
    240 
    241 struct ACodec::IdleToExecutingState : public ACodec::BaseState {
    242     IdleToExecutingState(ACodec *codec);
    243 
    244 protected:
    245     virtual bool onMessageReceived(const sp<AMessage> &msg);
    246     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    247     virtual void stateEntered();
    248 
    249 private:
    250     DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
    251 };
    252 
    253 ////////////////////////////////////////////////////////////////////////////////
    254 
    255 struct ACodec::ExecutingState : public ACodec::BaseState {
    256     ExecutingState(ACodec *codec);
    257 
    258     void submitRegularOutputBuffers();
    259     void submitOutputMetaBuffers();
    260     void submitOutputBuffers();
    261 
    262     // Submit output buffers to the decoder, submit input buffers to client
    263     // to fill with data.
    264     void resume();
    265 
    266     // Returns true iff input and output buffers are in play.
    267     bool active() const { return mActive; }
    268 
    269 protected:
    270     virtual PortMode getPortMode(OMX_U32 portIndex);
    271     virtual bool onMessageReceived(const sp<AMessage> &msg);
    272     virtual void stateEntered();
    273 
    274     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    275 
    276 private:
    277     bool mActive;
    278 
    279     DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
    280 };
    281 
    282 ////////////////////////////////////////////////////////////////////////////////
    283 
    284 struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
    285     OutputPortSettingsChangedState(ACodec *codec);
    286 
    287 protected:
    288     virtual PortMode getPortMode(OMX_U32 portIndex);
    289     virtual bool onMessageReceived(const sp<AMessage> &msg);
    290     virtual void stateEntered();
    291 
    292     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    293 
    294 private:
    295     DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
    296 };
    297 
    298 ////////////////////////////////////////////////////////////////////////////////
    299 
    300 struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
    301     ExecutingToIdleState(ACodec *codec);
    302 
    303 protected:
    304     virtual bool onMessageReceived(const sp<AMessage> &msg);
    305     virtual void stateEntered();
    306 
    307     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    308 
    309     virtual void onOutputBufferDrained(const sp<AMessage> &msg);
    310     virtual void onInputBufferFilled(const sp<AMessage> &msg);
    311 
    312 private:
    313     void changeStateIfWeOwnAllBuffers();
    314 
    315     bool mComponentNowIdle;
    316 
    317     DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
    318 };
    319 
    320 ////////////////////////////////////////////////////////////////////////////////
    321 
    322 struct ACodec::IdleToLoadedState : public ACodec::BaseState {
    323     IdleToLoadedState(ACodec *codec);
    324 
    325 protected:
    326     virtual bool onMessageReceived(const sp<AMessage> &msg);
    327     virtual void stateEntered();
    328 
    329     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    330 
    331 private:
    332     DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
    333 };
    334 
    335 ////////////////////////////////////////////////////////////////////////////////
    336 
    337 struct ACodec::FlushingState : public ACodec::BaseState {
    338     FlushingState(ACodec *codec);
    339 
    340 protected:
    341     virtual bool onMessageReceived(const sp<AMessage> &msg);
    342     virtual void stateEntered();
    343 
    344     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
    345 
    346     virtual void onOutputBufferDrained(const sp<AMessage> &msg);
    347     virtual void onInputBufferFilled(const sp<AMessage> &msg);
    348 
    349 private:
    350     bool mFlushComplete[2];
    351 
    352     void changeStateIfWeOwnAllBuffers();
    353 
    354     DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
    355 };
    356 
    357 ////////////////////////////////////////////////////////////////////////////////
    358 
    359 ACodec::ACodec()
    360     : mQuirks(0),
    361       mNode(NULL),
    362       mSentFormat(false),
    363       mIsEncoder(false),
    364       mUseMetadataOnEncoderOutput(false),
    365       mShutdownInProgress(false),
    366       mEncoderDelay(0),
    367       mEncoderPadding(0),
    368       mChannelMaskPresent(false),
    369       mChannelMask(0),
    370       mDequeueCounter(0),
    371       mStoreMetaDataInOutputBuffers(false),
    372       mMetaDataBuffersToSubmit(0),
    373       mRepeatFrameDelayUs(-1ll) {
    374     mUninitializedState = new UninitializedState(this);
    375     mLoadedState = new LoadedState(this);
    376     mLoadedToIdleState = new LoadedToIdleState(this);
    377     mIdleToExecutingState = new IdleToExecutingState(this);
    378     mExecutingState = new ExecutingState(this);
    379 
    380     mOutputPortSettingsChangedState =
    381         new OutputPortSettingsChangedState(this);
    382 
    383     mExecutingToIdleState = new ExecutingToIdleState(this);
    384     mIdleToLoadedState = new IdleToLoadedState(this);
    385     mFlushingState = new FlushingState(this);
    386 
    387     mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
    388     mInputEOSResult = OK;
    389 
    390     changeState(mUninitializedState);
    391 }
    392 
    393 ACodec::~ACodec() {
    394 }
    395 
    396 void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
    397     mNotify = msg;
    398 }
    399 
    400 void ACodec::initiateSetup(const sp<AMessage> &msg) {
    401     msg->setWhat(kWhatSetup);
    402     msg->setTarget(id());
    403     msg->post();
    404 }
    405 
    406 void ACodec::signalSetParameters(const sp<AMessage> &params) {
    407     sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
    408     msg->setMessage("params", params);
    409     msg->post();
    410 }
    411 
    412 void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
    413     msg->setWhat(kWhatAllocateComponent);
    414     msg->setTarget(id());
    415     msg->post();
    416 }
    417 
    418 void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
    419     msg->setWhat(kWhatConfigureComponent);
    420     msg->setTarget(id());
    421     msg->post();
    422 }
    423 
    424 void ACodec::initiateCreateInputSurface() {
    425     (new AMessage(kWhatCreateInputSurface, id()))->post();
    426 }
    427 
    428 void ACodec::signalEndOfInputStream() {
    429     (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
    430 }
    431 
    432 void ACodec::initiateStart() {
    433     (new AMessage(kWhatStart, id()))->post();
    434 }
    435 
    436 void ACodec::signalFlush() {
    437     ALOGV("[%s] signalFlush", mComponentName.c_str());
    438     (new AMessage(kWhatFlush, id()))->post();
    439 }
    440 
    441 void ACodec::signalResume() {
    442     (new AMessage(kWhatResume, id()))->post();
    443 }
    444 
    445 void ACodec::initiateShutdown(bool keepComponentAllocated) {
    446     sp<AMessage> msg = new AMessage(kWhatShutdown, id());
    447     msg->setInt32("keepComponentAllocated", keepComponentAllocated);
    448     msg->post();
    449 }
    450 
    451 void ACodec::signalRequestIDRFrame() {
    452     (new AMessage(kWhatRequestIDRFrame, id()))->post();
    453 }
    454 
    455 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
    456 // Some codecs may return input buffers before having them processed.
    457 // This causes a halt if we already signaled an EOS on the input
    458 // port.  For now keep submitting an output buffer if there was an
    459 // EOS on the input port, but not yet on the output port.
    460 void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
    461     if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
    462             mMetaDataBuffersToSubmit > 0) {
    463         (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post();
    464     }
    465 }
    466 
    467 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
    468     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
    469 
    470     CHECK(mDealer[portIndex] == NULL);
    471     CHECK(mBuffers[portIndex].isEmpty());
    472 
    473     status_t err;
    474     if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
    475         if (mStoreMetaDataInOutputBuffers) {
    476             err = allocateOutputMetaDataBuffers();
    477         } else {
    478             err = allocateOutputBuffersFromNativeWindow();
    479         }
    480     } else {
    481         OMX_PARAM_PORTDEFINITIONTYPE def;
    482         InitOMXParams(&def);
    483         def.nPortIndex = portIndex;
    484 
    485         err = mOMX->getParameter(
    486                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    487 
    488         if (err == OK) {
    489             ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
    490                     mComponentName.c_str(),
    491                     def.nBufferCountActual, def.nBufferSize,
    492                     portIndex == kPortIndexInput ? "input" : "output");
    493 
    494             size_t totalSize = def.nBufferCountActual * def.nBufferSize;
    495             mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
    496 
    497             for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
    498                 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
    499                 CHECK(mem.get() != NULL);
    500 
    501                 BufferInfo info;
    502                 info.mStatus = BufferInfo::OWNED_BY_US;
    503 
    504                 uint32_t requiresAllocateBufferBit =
    505                     (portIndex == kPortIndexInput)
    506                         ? OMXCodec::kRequiresAllocateBufferOnInputPorts
    507                         : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
    508 
    509                 if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
    510                         || mUseMetadataOnEncoderOutput) {
    511                     mem.clear();
    512 
    513                     void *ptr;
    514                     err = mOMX->allocateBuffer(
    515                             mNode, portIndex, def.nBufferSize, &info.mBufferID,
    516                             &ptr);
    517 
    518                     int32_t bufSize = mUseMetadataOnEncoderOutput ?
    519                             (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
    520 
    521                     info.mData = new ABuffer(ptr, bufSize);
    522                 } else if (mQuirks & requiresAllocateBufferBit) {
    523                     err = mOMX->allocateBufferWithBackup(
    524                             mNode, portIndex, mem, &info.mBufferID);
    525                 } else {
    526                     err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
    527                 }
    528 
    529                 if (mem != NULL) {
    530                     info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
    531                 }
    532 
    533                 mBuffers[portIndex].push(info);
    534             }
    535         }
    536     }
    537 
    538     if (err != OK) {
    539         return err;
    540     }
    541 
    542     sp<AMessage> notify = mNotify->dup();
    543     notify->setInt32("what", ACodec::kWhatBuffersAllocated);
    544 
    545     notify->setInt32("portIndex", portIndex);
    546 
    547     sp<PortDescription> desc = new PortDescription;
    548 
    549     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
    550         const BufferInfo &info = mBuffers[portIndex][i];
    551 
    552         desc->addBuffer(info.mBufferID, info.mData);
    553     }
    554 
    555     notify->setObject("portDesc", desc);
    556     notify->post();
    557 
    558     return OK;
    559 }
    560 
    561 status_t ACodec::configureOutputBuffersFromNativeWindow(
    562         OMX_U32 *bufferCount, OMX_U32 *bufferSize,
    563         OMX_U32 *minUndequeuedBuffers) {
    564     OMX_PARAM_PORTDEFINITIONTYPE def;
    565     InitOMXParams(&def);
    566     def.nPortIndex = kPortIndexOutput;
    567 
    568     status_t err = mOMX->getParameter(
    569             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    570 
    571     if (err != OK) {
    572         return err;
    573     }
    574 
    575     err = native_window_set_buffers_geometry(
    576             mNativeWindow.get(),
    577             def.format.video.nFrameWidth,
    578             def.format.video.nFrameHeight,
    579             def.format.video.eColorFormat);
    580 
    581     if (err != 0) {
    582         ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
    583                 strerror(-err), -err);
    584         return err;
    585     }
    586 
    587     // Set up the native window.
    588     OMX_U32 usage = 0;
    589     err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
    590     if (err != 0) {
    591         ALOGW("querying usage flags from OMX IL component failed: %d", err);
    592         // XXX: Currently this error is logged, but not fatal.
    593         usage = 0;
    594     }
    595 
    596     if (mFlags & kFlagIsSecure) {
    597         usage |= GRALLOC_USAGE_PROTECTED;
    598     }
    599 
    600     // Make sure to check whether either Stagefright or the video decoder
    601     // requested protected buffers.
    602     if (usage & GRALLOC_USAGE_PROTECTED) {
    603         // Verify that the ANativeWindow sends images directly to
    604         // SurfaceFlinger.
    605         int queuesToNativeWindow = 0;
    606         err = mNativeWindow->query(
    607                 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
    608                 &queuesToNativeWindow);
    609         if (err != 0) {
    610             ALOGE("error authenticating native window: %d", err);
    611             return err;
    612         }
    613         if (queuesToNativeWindow != 1) {
    614             ALOGE("native window could not be authenticated");
    615             return PERMISSION_DENIED;
    616         }
    617     }
    618 
    619     err = native_window_set_usage(
    620             mNativeWindow.get(),
    621             usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
    622 
    623     if (err != 0) {
    624         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
    625         return err;
    626     }
    627 
    628     *minUndequeuedBuffers = 0;
    629     err = mNativeWindow->query(
    630             mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
    631             (int *)minUndequeuedBuffers);
    632 
    633     if (err != 0) {
    634         ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
    635                 strerror(-err), -err);
    636         return err;
    637     }
    638 
    639     // XXX: Is this the right logic to use?  It's not clear to me what the OMX
    640     // buffer counts refer to - how do they account for the renderer holding on
    641     // to buffers?
    642     if (def.nBufferCountActual < def.nBufferCountMin + *minUndequeuedBuffers) {
    643         OMX_U32 newBufferCount = def.nBufferCountMin + *minUndequeuedBuffers;
    644         def.nBufferCountActual = newBufferCount;
    645         err = mOMX->setParameter(
    646                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    647 
    648         if (err != OK) {
    649             ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
    650                     mComponentName.c_str(), newBufferCount, err);
    651             return err;
    652         }
    653     }
    654 
    655     err = native_window_set_buffer_count(
    656             mNativeWindow.get(), def.nBufferCountActual);
    657 
    658     if (err != 0) {
    659         ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
    660                 -err);
    661         return err;
    662     }
    663 
    664     *bufferCount = def.nBufferCountActual;
    665     *bufferSize =  def.nBufferSize;
    666     return err;
    667 }
    668 
    669 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
    670     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
    671     status_t err = configureOutputBuffersFromNativeWindow(
    672             &bufferCount, &bufferSize, &minUndequeuedBuffers);
    673     if (err != 0)
    674         return err;
    675 
    676     ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
    677          "output port",
    678          mComponentName.c_str(), bufferCount, bufferSize);
    679 
    680     // Dequeue buffers and send them to OMX
    681     for (OMX_U32 i = 0; i < bufferCount; i++) {
    682         ANativeWindowBuffer *buf;
    683         err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
    684         if (err != 0) {
    685             ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
    686             break;
    687         }
    688 
    689         sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
    690         BufferInfo info;
    691         info.mStatus = BufferInfo::OWNED_BY_US;
    692         info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
    693         info.mGraphicBuffer = graphicBuffer;
    694         mBuffers[kPortIndexOutput].push(info);
    695 
    696         IOMX::buffer_id bufferId;
    697         err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
    698                 &bufferId);
    699         if (err != 0) {
    700             ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
    701                  "%d", i, err);
    702             break;
    703         }
    704 
    705         mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
    706 
    707         ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
    708              mComponentName.c_str(),
    709              bufferId, graphicBuffer.get());
    710     }
    711 
    712     OMX_U32 cancelStart;
    713     OMX_U32 cancelEnd;
    714 
    715     if (err != 0) {
    716         // If an error occurred while dequeuing we need to cancel any buffers
    717         // that were dequeued.
    718         cancelStart = 0;
    719         cancelEnd = mBuffers[kPortIndexOutput].size();
    720     } else {
    721         // Return the required minimum undequeued buffers to the native window.
    722         cancelStart = bufferCount - minUndequeuedBuffers;
    723         cancelEnd = bufferCount;
    724     }
    725 
    726     for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
    727         BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
    728         cancelBufferToNativeWindow(info);
    729     }
    730 
    731     return err;
    732 }
    733 
    734 status_t ACodec::allocateOutputMetaDataBuffers() {
    735     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
    736     status_t err = configureOutputBuffersFromNativeWindow(
    737             &bufferCount, &bufferSize, &minUndequeuedBuffers);
    738     if (err != 0)
    739         return err;
    740 
    741     ALOGV("[%s] Allocating %lu meta buffers on output port",
    742          mComponentName.c_str(), bufferCount);
    743 
    744     size_t totalSize = bufferCount * 8;
    745     mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
    746 
    747     // Dequeue buffers and send them to OMX
    748     for (OMX_U32 i = 0; i < bufferCount; i++) {
    749         BufferInfo info;
    750         info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
    751         info.mGraphicBuffer = NULL;
    752         info.mDequeuedAt = mDequeueCounter;
    753 
    754         sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
    755                 sizeof(struct VideoDecoderOutputMetaData));
    756         CHECK(mem.get() != NULL);
    757         info.mData = new ABuffer(mem->pointer(), mem->size());
    758 
    759         // we use useBuffer for metadata regardless of quirks
    760         err = mOMX->useBuffer(
    761                 mNode, kPortIndexOutput, mem, &info.mBufferID);
    762 
    763         mBuffers[kPortIndexOutput].push(info);
    764 
    765         ALOGV("[%s] allocated meta buffer with ID %p (pointer = %p)",
    766              mComponentName.c_str(), info.mBufferID, mem->pointer());
    767     }
    768 
    769     mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
    770     return err;
    771 }
    772 
    773 status_t ACodec::submitOutputMetaDataBuffer() {
    774     CHECK(mStoreMetaDataInOutputBuffers);
    775     if (mMetaDataBuffersToSubmit == 0)
    776         return OK;
    777 
    778     BufferInfo *info = dequeueBufferFromNativeWindow();
    779     if (info == NULL)
    780         return ERROR_IO;
    781 
    782     ALOGV("[%s] submitting output meta buffer ID %p for graphic buffer %p",
    783           mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
    784 
    785     --mMetaDataBuffersToSubmit;
    786     CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
    787              (status_t)OK);
    788 
    789     info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
    790     return OK;
    791 }
    792 
    793 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
    794     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
    795 
    796     ALOGV("[%s] Calling cancelBuffer on buffer %p",
    797          mComponentName.c_str(), info->mBufferID);
    798 
    799     int err = mNativeWindow->cancelBuffer(
    800         mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
    801 
    802     CHECK_EQ(err, 0);
    803 
    804     info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
    805 
    806     return OK;
    807 }
    808 
    809 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
    810     ANativeWindowBuffer *buf;
    811     int fenceFd = -1;
    812     CHECK(mNativeWindow.get() != NULL);
    813     if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
    814         ALOGE("dequeueBuffer failed.");
    815         return NULL;
    816     }
    817 
    818     BufferInfo *oldest = NULL;
    819     for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
    820         BufferInfo *info =
    821             &mBuffers[kPortIndexOutput].editItemAt(i);
    822 
    823         if (info->mGraphicBuffer != NULL &&
    824             info->mGraphicBuffer->handle == buf->handle) {
    825             CHECK_EQ((int)info->mStatus,
    826                      (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
    827 
    828             info->mStatus = BufferInfo::OWNED_BY_US;
    829 
    830             return info;
    831         }
    832 
    833         if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
    834             (oldest == NULL ||
    835              // avoid potential issues from counter rolling over
    836              mDequeueCounter - info->mDequeuedAt >
    837                     mDequeueCounter - oldest->mDequeuedAt)) {
    838             oldest = info;
    839         }
    840     }
    841 
    842     if (oldest) {
    843         CHECK(mStoreMetaDataInOutputBuffers);
    844 
    845         // discard buffer in LRU info and replace with new buffer
    846         oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
    847         oldest->mStatus = BufferInfo::OWNED_BY_US;
    848 
    849         mOMX->updateGraphicBufferInMeta(
    850                 mNode, kPortIndexOutput, oldest->mGraphicBuffer,
    851                 oldest->mBufferID);
    852 
    853         VideoDecoderOutputMetaData *metaData =
    854             reinterpret_cast<VideoDecoderOutputMetaData *>(
    855                     oldest->mData->base());
    856         CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
    857 
    858         ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
    859                 oldest - &mBuffers[kPortIndexOutput][0],
    860                 mDequeueCounter - oldest->mDequeuedAt,
    861                 metaData->pHandle,
    862                 oldest->mGraphicBuffer->handle, oldest->mData->base());
    863 
    864         return oldest;
    865     }
    866 
    867     TRESPASS();
    868 
    869     return NULL;
    870 }
    871 
    872 status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
    873     for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
    874         CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
    875     }
    876 
    877     mDealer[portIndex].clear();
    878 
    879     return OK;
    880 }
    881 
    882 status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
    883     for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
    884         BufferInfo *info =
    885             &mBuffers[kPortIndexOutput].editItemAt(i);
    886 
    887         // At this time some buffers may still be with the component
    888         // or being drained.
    889         if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
    890             info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
    891             CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
    892         }
    893     }
    894 
    895     return OK;
    896 }
    897 
    898 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
    899     BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
    900 
    901     CHECK(info->mStatus == BufferInfo::OWNED_BY_US
    902             || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
    903 
    904     if (portIndex == kPortIndexOutput && mNativeWindow != NULL
    905             && info->mStatus == BufferInfo::OWNED_BY_US) {
    906         CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
    907     }
    908 
    909     CHECK_EQ(mOMX->freeBuffer(
    910                 mNode, portIndex, info->mBufferID),
    911              (status_t)OK);
    912 
    913     mBuffers[portIndex].removeAt(i);
    914 
    915     return OK;
    916 }
    917 
    918 ACodec::BufferInfo *ACodec::findBufferByID(
    919         uint32_t portIndex, IOMX::buffer_id bufferID,
    920         ssize_t *index) {
    921     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
    922         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
    923 
    924         if (info->mBufferID == bufferID) {
    925             if (index != NULL) {
    926                 *index = i;
    927             }
    928             return info;
    929         }
    930     }
    931 
    932     TRESPASS();
    933 
    934     return NULL;
    935 }
    936 
    937 status_t ACodec::setComponentRole(
    938         bool isEncoder, const char *mime) {
    939     struct MimeToRole {
    940         const char *mime;
    941         const char *decoderRole;
    942         const char *encoderRole;
    943     };
    944 
    945     static const MimeToRole kMimeToRole[] = {
    946         { MEDIA_MIMETYPE_AUDIO_MPEG,
    947             "audio_decoder.mp3", "audio_encoder.mp3" },
    948         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
    949             "audio_decoder.mp1", "audio_encoder.mp1" },
    950         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
    951             "audio_decoder.mp2", "audio_encoder.mp2" },
    952         { MEDIA_MIMETYPE_AUDIO_AMR_NB,
    953             "audio_decoder.amrnb", "audio_encoder.amrnb" },
    954         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
    955             "audio_decoder.amrwb", "audio_encoder.amrwb" },
    956         { MEDIA_MIMETYPE_AUDIO_AAC,
    957             "audio_decoder.aac", "audio_encoder.aac" },
    958         { MEDIA_MIMETYPE_AUDIO_VORBIS,
    959             "audio_decoder.vorbis", "audio_encoder.vorbis" },
    960         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
    961             "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
    962         { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
    963             "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
    964         { MEDIA_MIMETYPE_VIDEO_AVC,
    965             "video_decoder.avc", "video_encoder.avc" },
    966         { MEDIA_MIMETYPE_VIDEO_MPEG4,
    967             "video_decoder.mpeg4", "video_encoder.mpeg4" },
    968         { MEDIA_MIMETYPE_VIDEO_H263,
    969             "video_decoder.h263", "video_encoder.h263" },
    970         { MEDIA_MIMETYPE_VIDEO_VP8,
    971             "video_decoder.vp8", "video_encoder.vp8" },
    972         { MEDIA_MIMETYPE_VIDEO_VP9,
    973             "video_decoder.vp9", "video_encoder.vp9" },
    974         { MEDIA_MIMETYPE_AUDIO_RAW,
    975             "audio_decoder.raw", "audio_encoder.raw" },
    976         { MEDIA_MIMETYPE_AUDIO_FLAC,
    977             "audio_decoder.flac", "audio_encoder.flac" },
    978         { MEDIA_MIMETYPE_AUDIO_MSGSM,
    979             "audio_decoder.gsm", "audio_encoder.gsm" },
    980     };
    981 
    982     static const size_t kNumMimeToRole =
    983         sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
    984 
    985     size_t i;
    986     for (i = 0; i < kNumMimeToRole; ++i) {
    987         if (!strcasecmp(mime, kMimeToRole[i].mime)) {
    988             break;
    989         }
    990     }
    991 
    992     if (i == kNumMimeToRole) {
    993         return ERROR_UNSUPPORTED;
    994     }
    995 
    996     const char *role =
    997         isEncoder ? kMimeToRole[i].encoderRole
    998                   : kMimeToRole[i].decoderRole;
    999 
   1000     if (role != NULL) {
   1001         OMX_PARAM_COMPONENTROLETYPE roleParams;
   1002         InitOMXParams(&roleParams);
   1003 
   1004         strncpy((char *)roleParams.cRole,
   1005                 role, OMX_MAX_STRINGNAME_SIZE - 1);
   1006 
   1007         roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
   1008 
   1009         status_t err = mOMX->setParameter(
   1010                 mNode, OMX_IndexParamStandardComponentRole,
   1011                 &roleParams, sizeof(roleParams));
   1012 
   1013         if (err != OK) {
   1014             ALOGW("[%s] Failed to set standard component role '%s'.",
   1015                  mComponentName.c_str(), role);
   1016 
   1017             return err;
   1018         }
   1019     }
   1020 
   1021     return OK;
   1022 }
   1023 
   1024 status_t ACodec::configureCodec(
   1025         const char *mime, const sp<AMessage> &msg) {
   1026     int32_t encoder;
   1027     if (!msg->findInt32("encoder", &encoder)) {
   1028         encoder = false;
   1029     }
   1030 
   1031     mIsEncoder = encoder;
   1032 
   1033     status_t err = setComponentRole(encoder /* isEncoder */, mime);
   1034 
   1035     if (err != OK) {
   1036         return err;
   1037     }
   1038 
   1039     int32_t bitRate = 0;
   1040     // FLAC encoder doesn't need a bitrate, other encoders do
   1041     if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
   1042             && !msg->findInt32("bitrate", &bitRate)) {
   1043         return INVALID_OPERATION;
   1044     }
   1045 
   1046     int32_t storeMeta;
   1047     if (encoder
   1048             && msg->findInt32("store-metadata-in-buffers", &storeMeta)
   1049             && storeMeta != 0) {
   1050         err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
   1051 
   1052         if (err != OK) {
   1053               ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
   1054                     mComponentName.c_str(), err);
   1055 
   1056               return err;
   1057           }
   1058       }
   1059 
   1060     int32_t prependSPSPPS = 0;
   1061     if (encoder
   1062             && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
   1063             && prependSPSPPS != 0) {
   1064         OMX_INDEXTYPE index;
   1065         err = mOMX->getExtensionIndex(
   1066                 mNode,
   1067                 "OMX.google.android.index.prependSPSPPSToIDRFrames",
   1068                 &index);
   1069 
   1070         if (err == OK) {
   1071             PrependSPSPPSToIDRFramesParams params;
   1072             InitOMXParams(&params);
   1073             params.bEnable = OMX_TRUE;
   1074 
   1075             err = mOMX->setParameter(
   1076                     mNode, index, &params, sizeof(params));
   1077         }
   1078 
   1079         if (err != OK) {
   1080             ALOGE("Encoder could not be configured to emit SPS/PPS before "
   1081                   "IDR frames. (err %d)", err);
   1082 
   1083             return err;
   1084         }
   1085     }
   1086 
   1087     // Only enable metadata mode on encoder output if encoder can prepend
   1088     // sps/pps to idr frames, since in metadata mode the bitstream is in an
   1089     // opaque handle, to which we don't have access.
   1090     int32_t video = !strncasecmp(mime, "video/", 6);
   1091     if (encoder && video) {
   1092         OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
   1093             && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
   1094             && storeMeta != 0);
   1095 
   1096         err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
   1097 
   1098         if (err != OK) {
   1099             ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
   1100                 mComponentName.c_str(), err);
   1101             mUseMetadataOnEncoderOutput = 0;
   1102         } else {
   1103             mUseMetadataOnEncoderOutput = enable;
   1104         }
   1105 
   1106         if (!msg->findInt64(
   1107                     "repeat-previous-frame-after",
   1108                     &mRepeatFrameDelayUs)) {
   1109             mRepeatFrameDelayUs = -1ll;
   1110         }
   1111     }
   1112 
   1113     // Always try to enable dynamic output buffers on native surface
   1114     sp<RefBase> obj;
   1115     int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
   1116             obj != NULL;
   1117     mStoreMetaDataInOutputBuffers = false;
   1118     if (!encoder && video && haveNativeWindow) {
   1119         err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE);
   1120         if (err != OK) {
   1121             ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
   1122                   mComponentName.c_str(), err);
   1123 
   1124             // if adaptive playback has been requested, try JB fallback
   1125             // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
   1126             // LARGE MEMORY REQUIREMENT
   1127 
   1128             // we will not do adaptive playback on software accessed
   1129             // surfaces as they never had to respond to changes in the
   1130             // crop window, and we don't trust that they will be able to.
   1131             int usageBits = 0;
   1132             bool canDoAdaptivePlayback;
   1133 
   1134             sp<NativeWindowWrapper> windowWrapper(
   1135                     static_cast<NativeWindowWrapper *>(obj.get()));
   1136             sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
   1137 
   1138             if (nativeWindow->query(
   1139                     nativeWindow.get(),
   1140                     NATIVE_WINDOW_CONSUMER_USAGE_BITS,
   1141                     &usageBits) != OK) {
   1142                 canDoAdaptivePlayback = false;
   1143             } else {
   1144                 canDoAdaptivePlayback =
   1145                     (usageBits &
   1146                             (GRALLOC_USAGE_SW_READ_MASK |
   1147                              GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
   1148             }
   1149 
   1150             int32_t maxWidth = 0, maxHeight = 0;
   1151             if (canDoAdaptivePlayback &&
   1152                 msg->findInt32("max-width", &maxWidth) &&
   1153                 msg->findInt32("max-height", &maxHeight)) {
   1154                 ALOGV("[%s] prepareForAdaptivePlayback(%ldx%ld)",
   1155                       mComponentName.c_str(), maxWidth, maxHeight);
   1156 
   1157                 err = mOMX->prepareForAdaptivePlayback(
   1158                         mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
   1159                 ALOGW_IF(err != OK,
   1160                         "[%s] prepareForAdaptivePlayback failed w/ err %d",
   1161                         mComponentName.c_str(), err);
   1162             }
   1163             // allow failure
   1164             err = OK;
   1165         } else {
   1166             ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str());
   1167             mStoreMetaDataInOutputBuffers = true;
   1168         }
   1169 
   1170         int32_t push;
   1171         if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
   1172                 && push != 0) {
   1173             mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
   1174         }
   1175     }
   1176 
   1177     if (video) {
   1178         if (encoder) {
   1179             err = setupVideoEncoder(mime, msg);
   1180         } else {
   1181             int32_t width, height;
   1182             if (!msg->findInt32("width", &width)
   1183                     || !msg->findInt32("height", &height)) {
   1184                 err = INVALID_OPERATION;
   1185             } else {
   1186                 err = setupVideoDecoder(mime, width, height);
   1187             }
   1188         }
   1189     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
   1190         int32_t numChannels, sampleRate;
   1191         if (!msg->findInt32("channel-count", &numChannels)
   1192                 || !msg->findInt32("sample-rate", &sampleRate)) {
   1193             // Since we did not always check for these, leave them optional
   1194             // and have the decoder figure it all out.
   1195             err = OK;
   1196         } else {
   1197             err = setupRawAudioFormat(
   1198                     encoder ? kPortIndexInput : kPortIndexOutput,
   1199                     sampleRate,
   1200                     numChannels);
   1201         }
   1202     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
   1203         int32_t numChannels, sampleRate;
   1204         if (!msg->findInt32("channel-count", &numChannels)
   1205                 || !msg->findInt32("sample-rate", &sampleRate)) {
   1206             err = INVALID_OPERATION;
   1207         } else {
   1208             int32_t isADTS, aacProfile;
   1209             if (!msg->findInt32("is-adts", &isADTS)) {
   1210                 isADTS = 0;
   1211             }
   1212             if (!msg->findInt32("aac-profile", &aacProfile)) {
   1213                 aacProfile = OMX_AUDIO_AACObjectNull;
   1214             }
   1215 
   1216             err = setupAACCodec(
   1217                     encoder, numChannels, sampleRate, bitRate, aacProfile,
   1218                     isADTS != 0);
   1219         }
   1220     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
   1221         err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
   1222     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
   1223         err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
   1224     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
   1225             || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
   1226         // These are PCM-like formats with a fixed sample rate but
   1227         // a variable number of channels.
   1228 
   1229         int32_t numChannels;
   1230         if (!msg->findInt32("channel-count", &numChannels)) {
   1231             err = INVALID_OPERATION;
   1232         } else {
   1233             err = setupG711Codec(encoder, numChannels);
   1234         }
   1235     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
   1236         int32_t numChannels, sampleRate, compressionLevel = -1;
   1237         if (encoder &&
   1238                 (!msg->findInt32("channel-count", &numChannels)
   1239                         || !msg->findInt32("sample-rate", &sampleRate))) {
   1240             ALOGE("missing channel count or sample rate for FLAC encoder");
   1241             err = INVALID_OPERATION;
   1242         } else {
   1243             if (encoder) {
   1244                 if (!msg->findInt32(
   1245                             "flac-compression-level", &compressionLevel)) {
   1246                     compressionLevel = 5;// default FLAC compression level
   1247                 } else if (compressionLevel < 0) {
   1248                     ALOGW("compression level %d outside [0..8] range, "
   1249                           "using 0",
   1250                           compressionLevel);
   1251                     compressionLevel = 0;
   1252                 } else if (compressionLevel > 8) {
   1253                     ALOGW("compression level %d outside [0..8] range, "
   1254                           "using 8",
   1255                           compressionLevel);
   1256                     compressionLevel = 8;
   1257                 }
   1258             }
   1259             err = setupFlacCodec(
   1260                     encoder, numChannels, sampleRate, compressionLevel);
   1261         }
   1262     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
   1263         int32_t numChannels, sampleRate;
   1264         if (encoder
   1265                 || !msg->findInt32("channel-count", &numChannels)
   1266                 || !msg->findInt32("sample-rate", &sampleRate)) {
   1267             err = INVALID_OPERATION;
   1268         } else {
   1269             err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
   1270         }
   1271     }
   1272 
   1273     if (err != OK) {
   1274         return err;
   1275     }
   1276 
   1277     if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
   1278         mEncoderDelay = 0;
   1279     }
   1280 
   1281     if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
   1282         mEncoderPadding = 0;
   1283     }
   1284 
   1285     if (msg->findInt32("channel-mask", &mChannelMask)) {
   1286         mChannelMaskPresent = true;
   1287     } else {
   1288         mChannelMaskPresent = false;
   1289     }
   1290 
   1291     int32_t maxInputSize;
   1292     if (msg->findInt32("max-input-size", &maxInputSize)) {
   1293         err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
   1294     } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
   1295         err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
   1296     }
   1297 
   1298     return err;
   1299 }
   1300 
   1301 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
   1302     OMX_PARAM_PORTDEFINITIONTYPE def;
   1303     InitOMXParams(&def);
   1304     def.nPortIndex = portIndex;
   1305 
   1306     status_t err = mOMX->getParameter(
   1307             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1308 
   1309     if (err != OK) {
   1310         return err;
   1311     }
   1312 
   1313     if (def.nBufferSize >= size) {
   1314         return OK;
   1315     }
   1316 
   1317     def.nBufferSize = size;
   1318 
   1319     err = mOMX->setParameter(
   1320             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1321 
   1322     if (err != OK) {
   1323         return err;
   1324     }
   1325 
   1326     err = mOMX->getParameter(
   1327             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1328 
   1329     if (err != OK) {
   1330         return err;
   1331     }
   1332 
   1333     CHECK(def.nBufferSize >= size);
   1334 
   1335     return OK;
   1336 }
   1337 
   1338 status_t ACodec::selectAudioPortFormat(
   1339         OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
   1340     OMX_AUDIO_PARAM_PORTFORMATTYPE format;
   1341     InitOMXParams(&format);
   1342 
   1343     format.nPortIndex = portIndex;
   1344     for (OMX_U32 index = 0;; ++index) {
   1345         format.nIndex = index;
   1346 
   1347         status_t err = mOMX->getParameter(
   1348                 mNode, OMX_IndexParamAudioPortFormat,
   1349                 &format, sizeof(format));
   1350 
   1351         if (err != OK) {
   1352             return err;
   1353         }
   1354 
   1355         if (format.eEncoding == desiredFormat) {
   1356             break;
   1357         }
   1358     }
   1359 
   1360     return mOMX->setParameter(
   1361             mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
   1362 }
   1363 
   1364 status_t ACodec::setupAACCodec(
   1365         bool encoder, int32_t numChannels, int32_t sampleRate,
   1366         int32_t bitRate, int32_t aacProfile, bool isADTS) {
   1367     if (encoder && isADTS) {
   1368         return -EINVAL;
   1369     }
   1370 
   1371     status_t err = setupRawAudioFormat(
   1372             encoder ? kPortIndexInput : kPortIndexOutput,
   1373             sampleRate,
   1374             numChannels);
   1375 
   1376     if (err != OK) {
   1377         return err;
   1378     }
   1379 
   1380     if (encoder) {
   1381         err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
   1382 
   1383         if (err != OK) {
   1384             return err;
   1385         }
   1386 
   1387         OMX_PARAM_PORTDEFINITIONTYPE def;
   1388         InitOMXParams(&def);
   1389         def.nPortIndex = kPortIndexOutput;
   1390 
   1391         err = mOMX->getParameter(
   1392                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1393 
   1394         if (err != OK) {
   1395             return err;
   1396         }
   1397 
   1398         def.format.audio.bFlagErrorConcealment = OMX_TRUE;
   1399         def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
   1400 
   1401         err = mOMX->setParameter(
   1402                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1403 
   1404         if (err != OK) {
   1405             return err;
   1406         }
   1407 
   1408         OMX_AUDIO_PARAM_AACPROFILETYPE profile;
   1409         InitOMXParams(&profile);
   1410         profile.nPortIndex = kPortIndexOutput;
   1411 
   1412         err = mOMX->getParameter(
   1413                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
   1414 
   1415         if (err != OK) {
   1416             return err;
   1417         }
   1418 
   1419         profile.nChannels = numChannels;
   1420 
   1421         profile.eChannelMode =
   1422             (numChannels == 1)
   1423                 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
   1424 
   1425         profile.nSampleRate = sampleRate;
   1426         profile.nBitRate = bitRate;
   1427         profile.nAudioBandWidth = 0;
   1428         profile.nFrameLength = 0;
   1429         profile.nAACtools = OMX_AUDIO_AACToolAll;
   1430         profile.nAACERtools = OMX_AUDIO_AACERNone;
   1431         profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
   1432         profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
   1433 
   1434         err = mOMX->setParameter(
   1435                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
   1436 
   1437         if (err != OK) {
   1438             return err;
   1439         }
   1440 
   1441         return err;
   1442     }
   1443 
   1444     OMX_AUDIO_PARAM_AACPROFILETYPE profile;
   1445     InitOMXParams(&profile);
   1446     profile.nPortIndex = kPortIndexInput;
   1447 
   1448     err = mOMX->getParameter(
   1449             mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
   1450 
   1451     if (err != OK) {
   1452         return err;
   1453     }
   1454 
   1455     profile.nChannels = numChannels;
   1456     profile.nSampleRate = sampleRate;
   1457 
   1458     profile.eAACStreamFormat =
   1459         isADTS
   1460             ? OMX_AUDIO_AACStreamFormatMP4ADTS
   1461             : OMX_AUDIO_AACStreamFormatMP4FF;
   1462 
   1463     return mOMX->setParameter(
   1464             mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
   1465 }
   1466 
   1467 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
   1468         bool isAMRWB, int32_t bps) {
   1469     if (isAMRWB) {
   1470         if (bps <= 6600) {
   1471             return OMX_AUDIO_AMRBandModeWB0;
   1472         } else if (bps <= 8850) {
   1473             return OMX_AUDIO_AMRBandModeWB1;
   1474         } else if (bps <= 12650) {
   1475             return OMX_AUDIO_AMRBandModeWB2;
   1476         } else if (bps <= 14250) {
   1477             return OMX_AUDIO_AMRBandModeWB3;
   1478         } else if (bps <= 15850) {
   1479             return OMX_AUDIO_AMRBandModeWB4;
   1480         } else if (bps <= 18250) {
   1481             return OMX_AUDIO_AMRBandModeWB5;
   1482         } else if (bps <= 19850) {
   1483             return OMX_AUDIO_AMRBandModeWB6;
   1484         } else if (bps <= 23050) {
   1485             return OMX_AUDIO_AMRBandModeWB7;
   1486         }
   1487 
   1488         // 23850 bps
   1489         return OMX_AUDIO_AMRBandModeWB8;
   1490     } else {  // AMRNB
   1491         if (bps <= 4750) {
   1492             return OMX_AUDIO_AMRBandModeNB0;
   1493         } else if (bps <= 5150) {
   1494             return OMX_AUDIO_AMRBandModeNB1;
   1495         } else if (bps <= 5900) {
   1496             return OMX_AUDIO_AMRBandModeNB2;
   1497         } else if (bps <= 6700) {
   1498             return OMX_AUDIO_AMRBandModeNB3;
   1499         } else if (bps <= 7400) {
   1500             return OMX_AUDIO_AMRBandModeNB4;
   1501         } else if (bps <= 7950) {
   1502             return OMX_AUDIO_AMRBandModeNB5;
   1503         } else if (bps <= 10200) {
   1504             return OMX_AUDIO_AMRBandModeNB6;
   1505         }
   1506 
   1507         // 12200 bps
   1508         return OMX_AUDIO_AMRBandModeNB7;
   1509     }
   1510 }
   1511 
   1512 status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
   1513     OMX_AUDIO_PARAM_AMRTYPE def;
   1514     InitOMXParams(&def);
   1515     def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
   1516 
   1517     status_t err =
   1518         mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
   1519 
   1520     if (err != OK) {
   1521         return err;
   1522     }
   1523 
   1524     def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
   1525     def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
   1526 
   1527     err = mOMX->setParameter(
   1528             mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
   1529 
   1530     if (err != OK) {
   1531         return err;
   1532     }
   1533 
   1534     return setupRawAudioFormat(
   1535             encoder ? kPortIndexInput : kPortIndexOutput,
   1536             isWAMR ? 16000 : 8000 /* sampleRate */,
   1537             1 /* numChannels */);
   1538 }
   1539 
   1540 status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
   1541     CHECK(!encoder);  // XXX TODO
   1542 
   1543     return setupRawAudioFormat(
   1544             kPortIndexInput, 8000 /* sampleRate */, numChannels);
   1545 }
   1546 
   1547 status_t ACodec::setupFlacCodec(
   1548         bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
   1549 
   1550     if (encoder) {
   1551         OMX_AUDIO_PARAM_FLACTYPE def;
   1552         InitOMXParams(&def);
   1553         def.nPortIndex = kPortIndexOutput;
   1554 
   1555         // configure compression level
   1556         status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
   1557         if (err != OK) {
   1558             ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
   1559             return err;
   1560         }
   1561         def.nCompressionLevel = compressionLevel;
   1562         err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
   1563         if (err != OK) {
   1564             ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
   1565             return err;
   1566         }
   1567     }
   1568 
   1569     return setupRawAudioFormat(
   1570             encoder ? kPortIndexInput : kPortIndexOutput,
   1571             sampleRate,
   1572             numChannels);
   1573 }
   1574 
   1575 status_t ACodec::setupRawAudioFormat(
   1576         OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
   1577     OMX_PARAM_PORTDEFINITIONTYPE def;
   1578     InitOMXParams(&def);
   1579     def.nPortIndex = portIndex;
   1580 
   1581     status_t err = mOMX->getParameter(
   1582             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1583 
   1584     if (err != OK) {
   1585         return err;
   1586     }
   1587 
   1588     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
   1589 
   1590     err = mOMX->setParameter(
   1591             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1592 
   1593     if (err != OK) {
   1594         return err;
   1595     }
   1596 
   1597     OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
   1598     InitOMXParams(&pcmParams);
   1599     pcmParams.nPortIndex = portIndex;
   1600 
   1601     err = mOMX->getParameter(
   1602             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
   1603 
   1604     if (err != OK) {
   1605         return err;
   1606     }
   1607 
   1608     pcmParams.nChannels = numChannels;
   1609     pcmParams.eNumData = OMX_NumericalDataSigned;
   1610     pcmParams.bInterleaved = OMX_TRUE;
   1611     pcmParams.nBitPerSample = 16;
   1612     pcmParams.nSamplingRate = sampleRate;
   1613     pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
   1614 
   1615     if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
   1616         return OMX_ErrorNone;
   1617     }
   1618 
   1619     return mOMX->setParameter(
   1620             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
   1621 }
   1622 
   1623 status_t ACodec::setVideoPortFormatType(
   1624         OMX_U32 portIndex,
   1625         OMX_VIDEO_CODINGTYPE compressionFormat,
   1626         OMX_COLOR_FORMATTYPE colorFormat) {
   1627     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
   1628     InitOMXParams(&format);
   1629     format.nPortIndex = portIndex;
   1630     format.nIndex = 0;
   1631     bool found = false;
   1632 
   1633     OMX_U32 index = 0;
   1634     for (;;) {
   1635         format.nIndex = index;
   1636         status_t err = mOMX->getParameter(
   1637                 mNode, OMX_IndexParamVideoPortFormat,
   1638                 &format, sizeof(format));
   1639 
   1640         if (err != OK) {
   1641             return err;
   1642         }
   1643 
   1644         // The following assertion is violated by TI's video decoder.
   1645         // CHECK_EQ(format.nIndex, index);
   1646 
   1647         if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
   1648             if (portIndex == kPortIndexInput
   1649                     && colorFormat == format.eColorFormat) {
   1650                 // eCompressionFormat does not seem right.
   1651                 found = true;
   1652                 break;
   1653             }
   1654             if (portIndex == kPortIndexOutput
   1655                     && compressionFormat == format.eCompressionFormat) {
   1656                 // eColorFormat does not seem right.
   1657                 found = true;
   1658                 break;
   1659             }
   1660         }
   1661 
   1662         if (format.eCompressionFormat == compressionFormat
   1663             && format.eColorFormat == colorFormat) {
   1664             found = true;
   1665             break;
   1666         }
   1667 
   1668         ++index;
   1669     }
   1670 
   1671     if (!found) {
   1672         return UNKNOWN_ERROR;
   1673     }
   1674 
   1675     status_t err = mOMX->setParameter(
   1676             mNode, OMX_IndexParamVideoPortFormat,
   1677             &format, sizeof(format));
   1678 
   1679     return err;
   1680 }
   1681 
   1682 status_t ACodec::setSupportedOutputFormat() {
   1683     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
   1684     InitOMXParams(&format);
   1685     format.nPortIndex = kPortIndexOutput;
   1686     format.nIndex = 0;
   1687 
   1688     status_t err = mOMX->getParameter(
   1689             mNode, OMX_IndexParamVideoPortFormat,
   1690             &format, sizeof(format));
   1691     CHECK_EQ(err, (status_t)OK);
   1692     CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
   1693 
   1694     return mOMX->setParameter(
   1695             mNode, OMX_IndexParamVideoPortFormat,
   1696             &format, sizeof(format));
   1697 }
   1698 
   1699 static const struct VideoCodingMapEntry {
   1700     const char *mMime;
   1701     OMX_VIDEO_CODINGTYPE mVideoCodingType;
   1702 } kVideoCodingMapEntry[] = {
   1703     { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
   1704     { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
   1705     { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
   1706     { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
   1707     { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
   1708     { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
   1709 };
   1710 
   1711 static status_t GetVideoCodingTypeFromMime(
   1712         const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
   1713     for (size_t i = 0;
   1714          i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
   1715          ++i) {
   1716         if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
   1717             *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
   1718             return OK;
   1719         }
   1720     }
   1721 
   1722     *codingType = OMX_VIDEO_CodingUnused;
   1723 
   1724     return ERROR_UNSUPPORTED;
   1725 }
   1726 
   1727 static status_t GetMimeTypeForVideoCoding(
   1728         OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
   1729     for (size_t i = 0;
   1730          i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
   1731          ++i) {
   1732         if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
   1733             *mime = kVideoCodingMapEntry[i].mMime;
   1734             return OK;
   1735         }
   1736     }
   1737 
   1738     mime->clear();
   1739 
   1740     return ERROR_UNSUPPORTED;
   1741 }
   1742 
   1743 status_t ACodec::setupVideoDecoder(
   1744         const char *mime, int32_t width, int32_t height) {
   1745     OMX_VIDEO_CODINGTYPE compressionFormat;
   1746     status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
   1747 
   1748     if (err != OK) {
   1749         return err;
   1750     }
   1751 
   1752     err = setVideoPortFormatType(
   1753             kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
   1754 
   1755     if (err != OK) {
   1756         return err;
   1757     }
   1758 
   1759     err = setSupportedOutputFormat();
   1760 
   1761     if (err != OK) {
   1762         return err;
   1763     }
   1764 
   1765     err = setVideoFormatOnPort(
   1766             kPortIndexInput, width, height, compressionFormat);
   1767 
   1768     if (err != OK) {
   1769         return err;
   1770     }
   1771 
   1772     err = setVideoFormatOnPort(
   1773             kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
   1774 
   1775     if (err != OK) {
   1776         return err;
   1777     }
   1778 
   1779     return OK;
   1780 }
   1781 
   1782 status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
   1783     int32_t tmp;
   1784     if (!msg->findInt32("color-format", &tmp)) {
   1785         return INVALID_OPERATION;
   1786     }
   1787 
   1788     OMX_COLOR_FORMATTYPE colorFormat =
   1789         static_cast<OMX_COLOR_FORMATTYPE>(tmp);
   1790 
   1791     status_t err = setVideoPortFormatType(
   1792             kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
   1793 
   1794     if (err != OK) {
   1795         ALOGE("[%s] does not support color format %d",
   1796               mComponentName.c_str(), colorFormat);
   1797 
   1798         return err;
   1799     }
   1800 
   1801     /* Input port configuration */
   1802 
   1803     OMX_PARAM_PORTDEFINITIONTYPE def;
   1804     InitOMXParams(&def);
   1805 
   1806     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
   1807 
   1808     def.nPortIndex = kPortIndexInput;
   1809 
   1810     err = mOMX->getParameter(
   1811             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1812 
   1813     if (err != OK) {
   1814         return err;
   1815     }
   1816 
   1817     int32_t width, height, bitrate;
   1818     if (!msg->findInt32("width", &width)
   1819             || !msg->findInt32("height", &height)
   1820             || !msg->findInt32("bitrate", &bitrate)) {
   1821         return INVALID_OPERATION;
   1822     }
   1823 
   1824     video_def->nFrameWidth = width;
   1825     video_def->nFrameHeight = height;
   1826 
   1827     int32_t stride;
   1828     if (!msg->findInt32("stride", &stride)) {
   1829         stride = width;
   1830     }
   1831 
   1832     video_def->nStride = stride;
   1833 
   1834     int32_t sliceHeight;
   1835     if (!msg->findInt32("slice-height", &sliceHeight)) {
   1836         sliceHeight = height;
   1837     }
   1838 
   1839     video_def->nSliceHeight = sliceHeight;
   1840 
   1841     def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
   1842 
   1843     float frameRate;
   1844     if (!msg->findFloat("frame-rate", &frameRate)) {
   1845         int32_t tmp;
   1846         if (!msg->findInt32("frame-rate", &tmp)) {
   1847             return INVALID_OPERATION;
   1848         }
   1849         frameRate = (float)tmp;
   1850     }
   1851 
   1852     video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
   1853     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
   1854     video_def->eColorFormat = colorFormat;
   1855 
   1856     err = mOMX->setParameter(
   1857             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1858 
   1859     if (err != OK) {
   1860         ALOGE("[%s] failed to set input port definition parameters.",
   1861               mComponentName.c_str());
   1862 
   1863         return err;
   1864     }
   1865 
   1866     /* Output port configuration */
   1867 
   1868     OMX_VIDEO_CODINGTYPE compressionFormat;
   1869     err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
   1870 
   1871     if (err != OK) {
   1872         return err;
   1873     }
   1874 
   1875     err = setVideoPortFormatType(
   1876             kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
   1877 
   1878     if (err != OK) {
   1879         ALOGE("[%s] does not support compression format %d",
   1880              mComponentName.c_str(), compressionFormat);
   1881 
   1882         return err;
   1883     }
   1884 
   1885     def.nPortIndex = kPortIndexOutput;
   1886 
   1887     err = mOMX->getParameter(
   1888             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1889 
   1890     if (err != OK) {
   1891         return err;
   1892     }
   1893 
   1894     video_def->nFrameWidth = width;
   1895     video_def->nFrameHeight = height;
   1896     video_def->xFramerate = 0;
   1897     video_def->nBitrate = bitrate;
   1898     video_def->eCompressionFormat = compressionFormat;
   1899     video_def->eColorFormat = OMX_COLOR_FormatUnused;
   1900 
   1901     err = mOMX->setParameter(
   1902             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   1903 
   1904     if (err != OK) {
   1905         ALOGE("[%s] failed to set output port definition parameters.",
   1906               mComponentName.c_str());
   1907 
   1908         return err;
   1909     }
   1910 
   1911     switch (compressionFormat) {
   1912         case OMX_VIDEO_CodingMPEG4:
   1913             err = setupMPEG4EncoderParameters(msg);
   1914             break;
   1915 
   1916         case OMX_VIDEO_CodingH263:
   1917             err = setupH263EncoderParameters(msg);
   1918             break;
   1919 
   1920         case OMX_VIDEO_CodingAVC:
   1921             err = setupAVCEncoderParameters(msg);
   1922             break;
   1923 
   1924         case OMX_VIDEO_CodingVP8:
   1925         case OMX_VIDEO_CodingVP9:
   1926             err = setupVPXEncoderParameters(msg);
   1927             break;
   1928 
   1929         default:
   1930             break;
   1931     }
   1932 
   1933     ALOGI("setupVideoEncoder succeeded");
   1934 
   1935     return err;
   1936 }
   1937 
   1938 status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
   1939     OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
   1940     InitOMXParams(&params);
   1941     params.nPortIndex = kPortIndexOutput;
   1942 
   1943     params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
   1944 
   1945     if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
   1946             params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
   1947         int32_t mbs;
   1948         if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
   1949             return INVALID_OPERATION;
   1950         }
   1951         params.nCirMBs = mbs;
   1952     }
   1953 
   1954     if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
   1955             params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
   1956         int32_t mbs;
   1957         if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
   1958             return INVALID_OPERATION;
   1959         }
   1960         params.nAirMBs = mbs;
   1961 
   1962         int32_t ref;
   1963         if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
   1964             return INVALID_OPERATION;
   1965         }
   1966         params.nAirRef = ref;
   1967     }
   1968 
   1969     status_t err = mOMX->setParameter(
   1970             mNode, OMX_IndexParamVideoIntraRefresh,
   1971             &params, sizeof(params));
   1972     return err;
   1973 }
   1974 
   1975 static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
   1976     if (iFramesInterval < 0) {
   1977         return 0xFFFFFFFF;
   1978     } else if (iFramesInterval == 0) {
   1979         return 0;
   1980     }
   1981     OMX_U32 ret = frameRate * iFramesInterval;
   1982     CHECK(ret > 1);
   1983     return ret;
   1984 }
   1985 
   1986 static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
   1987     int32_t tmp;
   1988     if (!msg->findInt32("bitrate-mode", &tmp)) {
   1989         return OMX_Video_ControlRateVariable;
   1990     }
   1991 
   1992     return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
   1993 }
   1994 
   1995 status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
   1996     int32_t bitrate, iFrameInterval;
   1997     if (!msg->findInt32("bitrate", &bitrate)
   1998             || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
   1999         return INVALID_OPERATION;
   2000     }
   2001 
   2002     OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
   2003 
   2004     float frameRate;
   2005     if (!msg->findFloat("frame-rate", &frameRate)) {
   2006         int32_t tmp;
   2007         if (!msg->findInt32("frame-rate", &tmp)) {
   2008             return INVALID_OPERATION;
   2009         }
   2010         frameRate = (float)tmp;
   2011     }
   2012 
   2013     OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
   2014     InitOMXParams(&mpeg4type);
   2015     mpeg4type.nPortIndex = kPortIndexOutput;
   2016 
   2017     status_t err = mOMX->getParameter(
   2018             mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
   2019 
   2020     if (err != OK) {
   2021         return err;
   2022     }
   2023 
   2024     mpeg4type.nSliceHeaderSpacing = 0;
   2025     mpeg4type.bSVH = OMX_FALSE;
   2026     mpeg4type.bGov = OMX_FALSE;
   2027 
   2028     mpeg4type.nAllowedPictureTypes =
   2029         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
   2030 
   2031     mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
   2032     if (mpeg4type.nPFrames == 0) {
   2033         mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
   2034     }
   2035     mpeg4type.nBFrames = 0;
   2036     mpeg4type.nIDCVLCThreshold = 0;
   2037     mpeg4type.bACPred = OMX_TRUE;
   2038     mpeg4type.nMaxPacketSize = 256;
   2039     mpeg4type.nTimeIncRes = 1000;
   2040     mpeg4type.nHeaderExtension = 0;
   2041     mpeg4type.bReversibleVLC = OMX_FALSE;
   2042 
   2043     int32_t profile;
   2044     if (msg->findInt32("profile", &profile)) {
   2045         int32_t level;
   2046         if (!msg->findInt32("level", &level)) {
   2047             return INVALID_OPERATION;
   2048         }
   2049 
   2050         err = verifySupportForProfileAndLevel(profile, level);
   2051 
   2052         if (err != OK) {
   2053             return err;
   2054         }
   2055 
   2056         mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
   2057         mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
   2058     }
   2059 
   2060     err = mOMX->setParameter(
   2061             mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
   2062 
   2063     if (err != OK) {
   2064         return err;
   2065     }
   2066 
   2067     err = configureBitrate(bitrate, bitrateMode);
   2068 
   2069     if (err != OK) {
   2070         return err;
   2071     }
   2072 
   2073     return setupErrorCorrectionParameters();
   2074 }
   2075 
   2076 status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
   2077     int32_t bitrate, iFrameInterval;
   2078     if (!msg->findInt32("bitrate", &bitrate)
   2079             || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
   2080         return INVALID_OPERATION;
   2081     }
   2082 
   2083     OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
   2084 
   2085     float frameRate;
   2086     if (!msg->findFloat("frame-rate", &frameRate)) {
   2087         int32_t tmp;
   2088         if (!msg->findInt32("frame-rate", &tmp)) {
   2089             return INVALID_OPERATION;
   2090         }
   2091         frameRate = (float)tmp;
   2092     }
   2093 
   2094     OMX_VIDEO_PARAM_H263TYPE h263type;
   2095     InitOMXParams(&h263type);
   2096     h263type.nPortIndex = kPortIndexOutput;
   2097 
   2098     status_t err = mOMX->getParameter(
   2099             mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
   2100 
   2101     if (err != OK) {
   2102         return err;
   2103     }
   2104 
   2105     h263type.nAllowedPictureTypes =
   2106         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
   2107 
   2108     h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
   2109     if (h263type.nPFrames == 0) {
   2110         h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
   2111     }
   2112     h263type.nBFrames = 0;
   2113 
   2114     int32_t profile;
   2115     if (msg->findInt32("profile", &profile)) {
   2116         int32_t level;
   2117         if (!msg->findInt32("level", &level)) {
   2118             return INVALID_OPERATION;
   2119         }
   2120 
   2121         err = verifySupportForProfileAndLevel(profile, level);
   2122 
   2123         if (err != OK) {
   2124             return err;
   2125         }
   2126 
   2127         h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
   2128         h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
   2129     }
   2130 
   2131     h263type.bPLUSPTYPEAllowed = OMX_FALSE;
   2132     h263type.bForceRoundingTypeToZero = OMX_FALSE;
   2133     h263type.nPictureHeaderRepetition = 0;
   2134     h263type.nGOBHeaderInterval = 0;
   2135 
   2136     err = mOMX->setParameter(
   2137             mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
   2138 
   2139     if (err != OK) {
   2140         return err;
   2141     }
   2142 
   2143     err = configureBitrate(bitrate, bitrateMode);
   2144 
   2145     if (err != OK) {
   2146         return err;
   2147     }
   2148 
   2149     return setupErrorCorrectionParameters();
   2150 }
   2151 
   2152 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
   2153     int32_t bitrate, iFrameInterval;
   2154     if (!msg->findInt32("bitrate", &bitrate)
   2155             || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
   2156         return INVALID_OPERATION;
   2157     }
   2158 
   2159     OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
   2160 
   2161     float frameRate;
   2162     if (!msg->findFloat("frame-rate", &frameRate)) {
   2163         int32_t tmp;
   2164         if (!msg->findInt32("frame-rate", &tmp)) {
   2165             return INVALID_OPERATION;
   2166         }
   2167         frameRate = (float)tmp;
   2168     }
   2169 
   2170     status_t err = OK;
   2171     int32_t intraRefreshMode = 0;
   2172     if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
   2173         err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
   2174         if (err != OK) {
   2175             ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
   2176                     err, intraRefreshMode);
   2177             return err;
   2178         }
   2179     }
   2180 
   2181     OMX_VIDEO_PARAM_AVCTYPE h264type;
   2182     InitOMXParams(&h264type);
   2183     h264type.nPortIndex = kPortIndexOutput;
   2184 
   2185     err = mOMX->getParameter(
   2186             mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
   2187 
   2188     if (err != OK) {
   2189         return err;
   2190     }
   2191 
   2192     h264type.nAllowedPictureTypes =
   2193         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
   2194 
   2195     int32_t profile;
   2196     if (msg->findInt32("profile", &profile)) {
   2197         int32_t level;
   2198         if (!msg->findInt32("level", &level)) {
   2199             return INVALID_OPERATION;
   2200         }
   2201 
   2202         err = verifySupportForProfileAndLevel(profile, level);
   2203 
   2204         if (err != OK) {
   2205             return err;
   2206         }
   2207 
   2208         h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
   2209         h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
   2210     }
   2211 
   2212     // XXX
   2213     if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
   2214         ALOGW("Use baseline profile instead of %d for AVC recording",
   2215             h264type.eProfile);
   2216         h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
   2217     }
   2218 
   2219     if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
   2220         h264type.nSliceHeaderSpacing = 0;
   2221         h264type.bUseHadamard = OMX_TRUE;
   2222         h264type.nRefFrames = 1;
   2223         h264type.nBFrames = 0;
   2224         h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
   2225         if (h264type.nPFrames == 0) {
   2226             h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
   2227         }
   2228         h264type.nRefIdx10ActiveMinus1 = 0;
   2229         h264type.nRefIdx11ActiveMinus1 = 0;
   2230         h264type.bEntropyCodingCABAC = OMX_FALSE;
   2231         h264type.bWeightedPPrediction = OMX_FALSE;
   2232         h264type.bconstIpred = OMX_FALSE;
   2233         h264type.bDirect8x8Inference = OMX_FALSE;
   2234         h264type.bDirectSpatialTemporal = OMX_FALSE;
   2235         h264type.nCabacInitIdc = 0;
   2236     }
   2237 
   2238     if (h264type.nBFrames != 0) {
   2239         h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
   2240     }
   2241 
   2242     h264type.bEnableUEP = OMX_FALSE;
   2243     h264type.bEnableFMO = OMX_FALSE;
   2244     h264type.bEnableASO = OMX_FALSE;
   2245     h264type.bEnableRS = OMX_FALSE;
   2246     h264type.bFrameMBsOnly = OMX_TRUE;
   2247     h264type.bMBAFF = OMX_FALSE;
   2248     h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
   2249 
   2250     err = mOMX->setParameter(
   2251             mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
   2252 
   2253     if (err != OK) {
   2254         return err;
   2255     }
   2256 
   2257     return configureBitrate(bitrate, bitrateMode);
   2258 }
   2259 
   2260 status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
   2261     int32_t bitrate;
   2262     if (!msg->findInt32("bitrate", &bitrate)) {
   2263         return INVALID_OPERATION;
   2264     }
   2265 
   2266     OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
   2267 
   2268     return configureBitrate(bitrate, bitrateMode);
   2269 }
   2270 
   2271 status_t ACodec::verifySupportForProfileAndLevel(
   2272         int32_t profile, int32_t level) {
   2273     OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
   2274     InitOMXParams(&params);
   2275     params.nPortIndex = kPortIndexOutput;
   2276 
   2277     for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
   2278         status_t err = mOMX->getParameter(
   2279                 mNode,
   2280                 OMX_IndexParamVideoProfileLevelQuerySupported,
   2281                 &params,
   2282                 sizeof(params));
   2283 
   2284         if (err != OK) {
   2285             return err;
   2286         }
   2287 
   2288         int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
   2289         int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
   2290 
   2291         if (profile == supportedProfile && level <= supportedLevel) {
   2292             return OK;
   2293         }
   2294     }
   2295 }
   2296 
   2297 status_t ACodec::configureBitrate(
   2298         int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
   2299     OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
   2300     InitOMXParams(&bitrateType);
   2301     bitrateType.nPortIndex = kPortIndexOutput;
   2302 
   2303     status_t err = mOMX->getParameter(
   2304             mNode, OMX_IndexParamVideoBitrate,
   2305             &bitrateType, sizeof(bitrateType));
   2306 
   2307     if (err != OK) {
   2308         return err;
   2309     }
   2310 
   2311     bitrateType.eControlRate = bitrateMode;
   2312     bitrateType.nTargetBitrate = bitrate;
   2313 
   2314     return mOMX->setParameter(
   2315             mNode, OMX_IndexParamVideoBitrate,
   2316             &bitrateType, sizeof(bitrateType));
   2317 }
   2318 
   2319 status_t ACodec::setupErrorCorrectionParameters() {
   2320     OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
   2321     InitOMXParams(&errorCorrectionType);
   2322     errorCorrectionType.nPortIndex = kPortIndexOutput;
   2323 
   2324     status_t err = mOMX->getParameter(
   2325             mNode, OMX_IndexParamVideoErrorCorrection,
   2326             &errorCorrectionType, sizeof(errorCorrectionType));
   2327 
   2328     if (err != OK) {
   2329         return OK;  // Optional feature. Ignore this failure
   2330     }
   2331 
   2332     errorCorrectionType.bEnableHEC = OMX_FALSE;
   2333     errorCorrectionType.bEnableResync = OMX_TRUE;
   2334     errorCorrectionType.nResynchMarkerSpacing = 256;
   2335     errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
   2336     errorCorrectionType.bEnableRVLC = OMX_FALSE;
   2337 
   2338     return mOMX->setParameter(
   2339             mNode, OMX_IndexParamVideoErrorCorrection,
   2340             &errorCorrectionType, sizeof(errorCorrectionType));
   2341 }
   2342 
   2343 status_t ACodec::setVideoFormatOnPort(
   2344         OMX_U32 portIndex,
   2345         int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
   2346     OMX_PARAM_PORTDEFINITIONTYPE def;
   2347     InitOMXParams(&def);
   2348     def.nPortIndex = portIndex;
   2349 
   2350     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
   2351 
   2352     status_t err = mOMX->getParameter(
   2353             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   2354 
   2355     CHECK_EQ(err, (status_t)OK);
   2356 
   2357     if (portIndex == kPortIndexInput) {
   2358         // XXX Need a (much) better heuristic to compute input buffer sizes.
   2359         const size_t X = 64 * 1024;
   2360         if (def.nBufferSize < X) {
   2361             def.nBufferSize = X;
   2362         }
   2363     }
   2364 
   2365     CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
   2366 
   2367     video_def->nFrameWidth = width;
   2368     video_def->nFrameHeight = height;
   2369 
   2370     if (portIndex == kPortIndexInput) {
   2371         video_def->eCompressionFormat = compressionFormat;
   2372         video_def->eColorFormat = OMX_COLOR_FormatUnused;
   2373     }
   2374 
   2375     err = mOMX->setParameter(
   2376             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
   2377 
   2378     return err;
   2379 }
   2380 
   2381 status_t ACodec::initNativeWindow() {
   2382     if (mNativeWindow != NULL) {
   2383         return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
   2384     }
   2385 
   2386     mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
   2387     return OK;
   2388 }
   2389 
   2390 size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
   2391     size_t n = 0;
   2392 
   2393     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
   2394         const BufferInfo &info = mBuffers[portIndex].itemAt(i);
   2395 
   2396         if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
   2397             ++n;
   2398         }
   2399     }
   2400 
   2401     return n;
   2402 }
   2403 
   2404 size_t ACodec::countBuffersOwnedByNativeWindow() const {
   2405     size_t n = 0;
   2406 
   2407     for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
   2408         const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
   2409 
   2410         if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
   2411             ++n;
   2412         }
   2413     }
   2414 
   2415     return n;
   2416 }
   2417 
   2418 void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
   2419     if (mNativeWindow == NULL) {
   2420         return;
   2421     }
   2422 
   2423     int minUndequeuedBufs = 0;
   2424     status_t err = mNativeWindow->query(
   2425             mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
   2426             &minUndequeuedBufs);
   2427 
   2428     if (err != OK) {
   2429         ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
   2430                 mComponentName.c_str(), strerror(-err), -err);
   2431 
   2432         minUndequeuedBufs = 0;
   2433     }
   2434 
   2435     while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs
   2436             && dequeueBufferFromNativeWindow() != NULL) {
   2437         // these buffers will be submitted as regular buffers; account for this
   2438         if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
   2439             --mMetaDataBuffersToSubmit;
   2440         }
   2441     }
   2442 }
   2443 
   2444 bool ACodec::allYourBuffersAreBelongToUs(
   2445         OMX_U32 portIndex) {
   2446     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
   2447         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
   2448 
   2449         if (info->mStatus != BufferInfo::OWNED_BY_US
   2450                 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
   2451             ALOGV("[%s] Buffer %p on port %ld still has status %d",
   2452                     mComponentName.c_str(),
   2453                     info->mBufferID, portIndex, info->mStatus);
   2454             return false;
   2455         }
   2456     }
   2457 
   2458     return true;
   2459 }
   2460 
   2461 bool ACodec::allYourBuffersAreBelongToUs() {
   2462     return allYourBuffersAreBelongToUs(kPortIndexInput)
   2463         && allYourBuffersAreBelongToUs(kPortIndexOutput);
   2464 }
   2465 
   2466 void ACodec::deferMessage(const sp<AMessage> &msg) {
   2467     bool wasEmptyBefore = mDeferredQueue.empty();
   2468     mDeferredQueue.push_back(msg);
   2469 }
   2470 
   2471 void ACodec::processDeferredMessages() {
   2472     List<sp<AMessage> > queue = mDeferredQueue;
   2473     mDeferredQueue.clear();
   2474 
   2475     List<sp<AMessage> >::iterator it = queue.begin();
   2476     while (it != queue.end()) {
   2477         onMessageReceived(*it++);
   2478     }
   2479 }
   2480 
   2481 void ACodec::sendFormatChange(const sp<AMessage> &reply) {
   2482     sp<AMessage> notify = mNotify->dup();
   2483     notify->setInt32("what", kWhatOutputFormatChanged);
   2484 
   2485     OMX_PARAM_PORTDEFINITIONTYPE def;
   2486     InitOMXParams(&def);
   2487     def.nPortIndex = kPortIndexOutput;
   2488 
   2489     CHECK_EQ(mOMX->getParameter(
   2490                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
   2491              (status_t)OK);
   2492 
   2493     CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
   2494 
   2495     switch (def.eDomain) {
   2496         case OMX_PortDomainVideo:
   2497         {
   2498             OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
   2499 
   2500             AString mime;
   2501             if (!mIsEncoder) {
   2502                 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
   2503             } else if (GetMimeTypeForVideoCoding(
   2504                         videoDef->eCompressionFormat, &mime) != OK) {
   2505                 notify->setString("mime", "application/octet-stream");
   2506             } else {
   2507                 notify->setString("mime", mime.c_str());
   2508             }
   2509 
   2510             notify->setInt32("width", videoDef->nFrameWidth);
   2511             notify->setInt32("height", videoDef->nFrameHeight);
   2512 
   2513             if (!mIsEncoder) {
   2514                 notify->setInt32("stride", videoDef->nStride);
   2515                 notify->setInt32("slice-height", videoDef->nSliceHeight);
   2516                 notify->setInt32("color-format", videoDef->eColorFormat);
   2517 
   2518                 OMX_CONFIG_RECTTYPE rect;
   2519                 InitOMXParams(&rect);
   2520                 rect.nPortIndex = kPortIndexOutput;
   2521 
   2522                 if (mOMX->getConfig(
   2523                             mNode, OMX_IndexConfigCommonOutputCrop,
   2524                             &rect, sizeof(rect)) != OK) {
   2525                     rect.nLeft = 0;
   2526                     rect.nTop = 0;
   2527                     rect.nWidth = videoDef->nFrameWidth;
   2528                     rect.nHeight = videoDef->nFrameHeight;
   2529                 }
   2530 
   2531                 CHECK_GE(rect.nLeft, 0);
   2532                 CHECK_GE(rect.nTop, 0);
   2533                 CHECK_GE(rect.nWidth, 0u);
   2534                 CHECK_GE(rect.nHeight, 0u);
   2535                 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
   2536                 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
   2537 
   2538                 notify->setRect(
   2539                         "crop",
   2540                         rect.nLeft,
   2541                         rect.nTop,
   2542                         rect.nLeft + rect.nWidth - 1,
   2543                         rect.nTop + rect.nHeight - 1);
   2544 
   2545                 if (mNativeWindow != NULL) {
   2546                     reply->setRect(
   2547                             "crop",
   2548                             rect.nLeft,
   2549                             rect.nTop,
   2550                             rect.nLeft + rect.nWidth,
   2551                             rect.nTop + rect.nHeight);
   2552                 }
   2553             }
   2554             break;
   2555         }
   2556 
   2557         case OMX_PortDomainAudio:
   2558         {
   2559             OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
   2560 
   2561             switch (audioDef->eEncoding) {
   2562                 case OMX_AUDIO_CodingPCM:
   2563                 {
   2564                     OMX_AUDIO_PARAM_PCMMODETYPE params;
   2565                     InitOMXParams(&params);
   2566                     params.nPortIndex = kPortIndexOutput;
   2567 
   2568                     CHECK_EQ(mOMX->getParameter(
   2569                                 mNode, OMX_IndexParamAudioPcm,
   2570                                 &params, sizeof(params)),
   2571                              (status_t)OK);
   2572 
   2573                     CHECK_GT(params.nChannels, 0);
   2574                     CHECK(params.nChannels == 1 || params.bInterleaved);
   2575                     CHECK_EQ(params.nBitPerSample, 16u);
   2576 
   2577                     CHECK_EQ((int)params.eNumData,
   2578                              (int)OMX_NumericalDataSigned);
   2579 
   2580                     CHECK_EQ((int)params.ePCMMode,
   2581                              (int)OMX_AUDIO_PCMModeLinear);
   2582 
   2583                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
   2584                     notify->setInt32("channel-count", params.nChannels);
   2585                     notify->setInt32("sample-rate", params.nSamplingRate);
   2586                     if (mEncoderDelay + mEncoderPadding) {
   2587                         size_t frameSize = params.nChannels * sizeof(int16_t);
   2588                         if (mSkipCutBuffer != NULL) {
   2589                             size_t prevbufsize = mSkipCutBuffer->size();
   2590                             if (prevbufsize != 0) {
   2591                                 ALOGW("Replacing SkipCutBuffer holding %d "
   2592                                       "bytes",
   2593                                       prevbufsize);
   2594                             }
   2595                         }
   2596                         mSkipCutBuffer = new SkipCutBuffer(
   2597                                 mEncoderDelay * frameSize,
   2598                                 mEncoderPadding * frameSize);
   2599                     }
   2600 
   2601                     if (mChannelMaskPresent) {
   2602                         notify->setInt32("channel-mask", mChannelMask);
   2603                     }
   2604                     break;
   2605                 }
   2606 
   2607                 case OMX_AUDIO_CodingAAC:
   2608                 {
   2609                     OMX_AUDIO_PARAM_AACPROFILETYPE params;
   2610                     InitOMXParams(&params);
   2611                     params.nPortIndex = kPortIndexOutput;
   2612 
   2613                     CHECK_EQ(mOMX->getParameter(
   2614                                 mNode, OMX_IndexParamAudioAac,
   2615                                 &params, sizeof(params)),
   2616                              (status_t)OK);
   2617 
   2618                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
   2619                     notify->setInt32("channel-count", params.nChannels);
   2620                     notify->setInt32("sample-rate", params.nSampleRate);
   2621                     break;
   2622                 }
   2623 
   2624                 case OMX_AUDIO_CodingAMR:
   2625                 {
   2626                     OMX_AUDIO_PARAM_AMRTYPE params;
   2627                     InitOMXParams(&params);
   2628                     params.nPortIndex = kPortIndexOutput;
   2629 
   2630                     CHECK_EQ(mOMX->getParameter(
   2631                                 mNode, OMX_IndexParamAudioAmr,
   2632                                 &params, sizeof(params)),
   2633                              (status_t)OK);
   2634 
   2635                     notify->setInt32("channel-count", 1);
   2636                     if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
   2637                         notify->setString(
   2638                                 "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
   2639 
   2640                         notify->setInt32("sample-rate", 16000);
   2641                     } else {
   2642                         notify->setString(
   2643                                 "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
   2644 
   2645                         notify->setInt32("sample-rate", 8000);
   2646                     }
   2647                     break;
   2648                 }
   2649 
   2650                 case OMX_AUDIO_CodingFLAC:
   2651                 {
   2652                     OMX_AUDIO_PARAM_FLACTYPE params;
   2653                     InitOMXParams(&params);
   2654                     params.nPortIndex = kPortIndexOutput;
   2655 
   2656                     CHECK_EQ(mOMX->getParameter(
   2657                                 mNode, OMX_IndexParamAudioFlac,
   2658                                 &params, sizeof(params)),
   2659                              (status_t)OK);
   2660 
   2661                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
   2662                     notify->setInt32("channel-count", params.nChannels);
   2663                     notify->setInt32("sample-rate", params.nSampleRate);
   2664                     break;
   2665                 }
   2666 
   2667                 default:
   2668                     TRESPASS();
   2669             }
   2670             break;
   2671         }
   2672 
   2673         default:
   2674             TRESPASS();
   2675     }
   2676 
   2677     notify->post();
   2678 
   2679     mSentFormat = true;
   2680 }
   2681 
   2682 void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
   2683     sp<AMessage> notify = mNotify->dup();
   2684     notify->setInt32("what", ACodec::kWhatError);
   2685     notify->setInt32("omx-error", error);
   2686     notify->setInt32("err", internalError);
   2687     notify->post();
   2688 }
   2689 
   2690 status_t ACodec::pushBlankBuffersToNativeWindow() {
   2691     status_t err = NO_ERROR;
   2692     ANativeWindowBuffer* anb = NULL;
   2693     int numBufs = 0;
   2694     int minUndequeuedBufs = 0;
   2695 
   2696     // We need to reconnect to the ANativeWindow as a CPU client to ensure that
   2697     // no frames get dropped by SurfaceFlinger assuming that these are video
   2698     // frames.
   2699     err = native_window_api_disconnect(mNativeWindow.get(),
   2700             NATIVE_WINDOW_API_MEDIA);
   2701     if (err != NO_ERROR) {
   2702         ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
   2703                 strerror(-err), -err);
   2704         return err;
   2705     }
   2706 
   2707     err = native_window_api_connect(mNativeWindow.get(),
   2708             NATIVE_WINDOW_API_CPU);
   2709     if (err != NO_ERROR) {
   2710         ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
   2711                 strerror(-err), -err);
   2712         return err;
   2713     }
   2714 
   2715     err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
   2716             HAL_PIXEL_FORMAT_RGBX_8888);
   2717     if (err != NO_ERROR) {
   2718         ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
   2719                 strerror(-err), -err);
   2720         goto error;
   2721     }
   2722 
   2723     err = native_window_set_scaling_mode(mNativeWindow.get(),
   2724                 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
   2725     if (err != NO_ERROR) {
   2726         ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
   2727               strerror(-err), -err);
   2728         goto error;
   2729     }
   2730 
   2731     err = native_window_set_usage(mNativeWindow.get(),
   2732             GRALLOC_USAGE_SW_WRITE_OFTEN);
   2733     if (err != NO_ERROR) {
   2734         ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
   2735                 strerror(-err), -err);
   2736         goto error;
   2737     }
   2738 
   2739     err = mNativeWindow->query(mNativeWindow.get(),
   2740             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
   2741     if (err != NO_ERROR) {
   2742         ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
   2743                 "failed: %s (%d)", strerror(-err), -err);
   2744         goto error;
   2745     }
   2746 
   2747     numBufs = minUndequeuedBufs + 1;
   2748     err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
   2749     if (err != NO_ERROR) {
   2750         ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
   2751                 strerror(-err), -err);
   2752         goto error;
   2753     }
   2754 
   2755     // We  push numBufs + 1 buffers to ensure that we've drawn into the same
   2756     // buffer twice.  This should guarantee that the buffer has been displayed
   2757     // on the screen and then been replaced, so an previous video frames are
   2758     // guaranteed NOT to be currently displayed.
   2759     for (int i = 0; i < numBufs + 1; i++) {
   2760         int fenceFd = -1;
   2761         err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
   2762         if (err != NO_ERROR) {
   2763             ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
   2764                     strerror(-err), -err);
   2765             goto error;
   2766         }
   2767 
   2768         sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
   2769 
   2770         // Fill the buffer with the a 1x1 checkerboard pattern ;)
   2771         uint32_t* img = NULL;
   2772         err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
   2773         if (err != NO_ERROR) {
   2774             ALOGE("error pushing blank frames: lock failed: %s (%d)",
   2775                     strerror(-err), -err);
   2776             goto error;
   2777         }
   2778 
   2779         *img = 0;
   2780 
   2781         err = buf->unlock();
   2782         if (err != NO_ERROR) {
   2783             ALOGE("error pushing blank frames: unlock failed: %s (%d)",
   2784                     strerror(-err), -err);
   2785             goto error;
   2786         }
   2787 
   2788         err = mNativeWindow->queueBuffer(mNativeWindow.get(),
   2789                 buf->getNativeBuffer(), -1);
   2790         if (err != NO_ERROR) {
   2791             ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
   2792                     strerror(-err), -err);
   2793             goto error;
   2794         }
   2795 
   2796         anb = NULL;
   2797     }
   2798 
   2799 error:
   2800 
   2801     if (err != NO_ERROR) {
   2802         // Clean up after an error.
   2803         if (anb != NULL) {
   2804             mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
   2805         }
   2806 
   2807         native_window_api_disconnect(mNativeWindow.get(),
   2808                 NATIVE_WINDOW_API_CPU);
   2809         native_window_api_connect(mNativeWindow.get(),
   2810                 NATIVE_WINDOW_API_MEDIA);
   2811 
   2812         return err;
   2813     } else {
   2814         // Clean up after success.
   2815         err = native_window_api_disconnect(mNativeWindow.get(),
   2816                 NATIVE_WINDOW_API_CPU);
   2817         if (err != NO_ERROR) {
   2818             ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
   2819                     strerror(-err), -err);
   2820             return err;
   2821         }
   2822 
   2823         err = native_window_api_connect(mNativeWindow.get(),
   2824                 NATIVE_WINDOW_API_MEDIA);
   2825         if (err != NO_ERROR) {
   2826             ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
   2827                     strerror(-err), -err);
   2828             return err;
   2829         }
   2830 
   2831         return NO_ERROR;
   2832     }
   2833 }
   2834 
   2835 ////////////////////////////////////////////////////////////////////////////////
   2836 
   2837 ACodec::PortDescription::PortDescription() {
   2838 }
   2839 
   2840 status_t ACodec::requestIDRFrame() {
   2841     if (!mIsEncoder) {
   2842         return ERROR_UNSUPPORTED;
   2843     }
   2844 
   2845     OMX_CONFIG_INTRAREFRESHVOPTYPE params;
   2846     InitOMXParams(&params);
   2847 
   2848     params.nPortIndex = kPortIndexOutput;
   2849     params.IntraRefreshVOP = OMX_TRUE;
   2850 
   2851     return mOMX->setConfig(
   2852             mNode,
   2853             OMX_IndexConfigVideoIntraVOPRefresh,
   2854             &params,
   2855             sizeof(params));
   2856 }
   2857 
   2858 void ACodec::PortDescription::addBuffer(
   2859         IOMX::buffer_id id, const sp<ABuffer> &buffer) {
   2860     mBufferIDs.push_back(id);
   2861     mBuffers.push_back(buffer);
   2862 }
   2863 
   2864 size_t ACodec::PortDescription::countBuffers() {
   2865     return mBufferIDs.size();
   2866 }
   2867 
   2868 IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
   2869     return mBufferIDs.itemAt(index);
   2870 }
   2871 
   2872 sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
   2873     return mBuffers.itemAt(index);
   2874 }
   2875 
   2876 ////////////////////////////////////////////////////////////////////////////////
   2877 
   2878 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
   2879     : AState(parentState),
   2880       mCodec(codec) {
   2881 }
   2882 
   2883 ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
   2884     return KEEP_BUFFERS;
   2885 }
   2886 
   2887 bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
   2888     switch (msg->what()) {
   2889         case kWhatInputBufferFilled:
   2890         {
   2891             onInputBufferFilled(msg);
   2892             break;
   2893         }
   2894 
   2895         case kWhatOutputBufferDrained:
   2896         {
   2897             onOutputBufferDrained(msg);
   2898             break;
   2899         }
   2900 
   2901         case ACodec::kWhatOMXMessage:
   2902         {
   2903             return onOMXMessage(msg);
   2904         }
   2905 
   2906         case ACodec::kWhatCreateInputSurface:
   2907         case ACodec::kWhatSignalEndOfInputStream:
   2908         {
   2909             ALOGE("Message 0x%x was not handled", msg->what());
   2910             mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
   2911             return true;
   2912         }
   2913 
   2914         case ACodec::kWhatOMXDied:
   2915         {
   2916             ALOGE("OMX/mediaserver died, signalling error!");
   2917             mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
   2918             break;
   2919         }
   2920 
   2921         default:
   2922             return false;
   2923     }
   2924 
   2925     return true;
   2926 }
   2927 
   2928 bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
   2929     int32_t type;
   2930     CHECK(msg->findInt32("type", &type));
   2931 
   2932     IOMX::node_id nodeID;
   2933     CHECK(msg->findPointer("node", &nodeID));
   2934     CHECK_EQ(nodeID, mCodec->mNode);
   2935 
   2936     switch (type) {
   2937         case omx_message::EVENT:
   2938         {
   2939             int32_t event, data1, data2;
   2940             CHECK(msg->findInt32("event", &event));
   2941             CHECK(msg->findInt32("data1", &data1));
   2942             CHECK(msg->findInt32("data2", &data2));
   2943 
   2944             if (event == OMX_EventCmdComplete
   2945                     && data1 == OMX_CommandFlush
   2946                     && data2 == (int32_t)OMX_ALL) {
   2947                 // Use of this notification is not consistent across
   2948                 // implementations. We'll drop this notification and rely
   2949                 // on flush-complete notifications on the individual port
   2950                 // indices instead.
   2951 
   2952                 return true;
   2953             }
   2954 
   2955             return onOMXEvent(
   2956                     static_cast<OMX_EVENTTYPE>(event),
   2957                     static_cast<OMX_U32>(data1),
   2958                     static_cast<OMX_U32>(data2));
   2959         }
   2960 
   2961         case omx_message::EMPTY_BUFFER_DONE:
   2962         {
   2963             IOMX::buffer_id bufferID;
   2964             CHECK(msg->findPointer("buffer", &bufferID));
   2965 
   2966             return onOMXEmptyBufferDone(bufferID);
   2967         }
   2968 
   2969         case omx_message::FILL_BUFFER_DONE:
   2970         {
   2971             IOMX::buffer_id bufferID;
   2972             CHECK(msg->findPointer("buffer", &bufferID));
   2973 
   2974             int32_t rangeOffset, rangeLength, flags;
   2975             int64_t timeUs;
   2976             void *platformPrivate;
   2977             void *dataPtr;
   2978 
   2979             CHECK(msg->findInt32("range_offset", &rangeOffset));
   2980             CHECK(msg->findInt32("range_length", &rangeLength));
   2981             CHECK(msg->findInt32("flags", &flags));
   2982             CHECK(msg->findInt64("timestamp", &timeUs));
   2983             CHECK(msg->findPointer("platform_private", &platformPrivate));
   2984             CHECK(msg->findPointer("data_ptr", &dataPtr));
   2985 
   2986             return onOMXFillBufferDone(
   2987                     bufferID,
   2988                     (size_t)rangeOffset, (size_t)rangeLength,
   2989                     (OMX_U32)flags,
   2990                     timeUs,
   2991                     platformPrivate,
   2992                     dataPtr);
   2993         }
   2994 
   2995         default:
   2996             TRESPASS();
   2997             break;
   2998     }
   2999 }
   3000 
   3001 bool ACodec::BaseState::onOMXEvent(
   3002         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   3003     if (event != OMX_EventError) {
   3004         ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
   3005              mCodec->mComponentName.c_str(), event, data1, data2);
   3006 
   3007         return false;
   3008     }
   3009 
   3010     ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
   3011 
   3012     mCodec->signalError((OMX_ERRORTYPE)data1);
   3013 
   3014     return true;
   3015 }
   3016 
   3017 bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
   3018     ALOGV("[%s] onOMXEmptyBufferDone %p",
   3019          mCodec->mComponentName.c_str(), bufferID);
   3020 
   3021     BufferInfo *info =
   3022         mCodec->findBufferByID(kPortIndexInput, bufferID);
   3023 
   3024     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
   3025     info->mStatus = BufferInfo::OWNED_BY_US;
   3026 
   3027     const sp<AMessage> &bufferMeta = info->mData->meta();
   3028     void *mediaBuffer;
   3029     if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer)
   3030             && mediaBuffer != NULL) {
   3031         // We're in "store-metadata-in-buffers" mode, the underlying
   3032         // OMX component had access to data that's implicitly refcounted
   3033         // by this "mediaBuffer" object. Now that the OMX component has
   3034         // told us that it's done with the input buffer, we can decrement
   3035         // the mediaBuffer's reference count.
   3036 
   3037         ALOGV("releasing mbuf %p", mediaBuffer);
   3038 
   3039         ((MediaBuffer *)mediaBuffer)->release();
   3040         mediaBuffer = NULL;
   3041 
   3042         bufferMeta->setPointer("mediaBuffer", NULL);
   3043     }
   3044 
   3045     PortMode mode = getPortMode(kPortIndexInput);
   3046 
   3047     switch (mode) {
   3048         case KEEP_BUFFERS:
   3049             break;
   3050 
   3051         case RESUBMIT_BUFFERS:
   3052             postFillThisBuffer(info);
   3053             break;
   3054 
   3055         default:
   3056         {
   3057             CHECK_EQ((int)mode, (int)FREE_BUFFERS);
   3058             TRESPASS();  // Not currently used
   3059             break;
   3060         }
   3061     }
   3062 
   3063     return true;
   3064 }
   3065 
   3066 void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
   3067     if (mCodec->mPortEOS[kPortIndexInput]) {
   3068         return;
   3069     }
   3070 
   3071     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
   3072 
   3073     sp<AMessage> notify = mCodec->mNotify->dup();
   3074     notify->setInt32("what", ACodec::kWhatFillThisBuffer);
   3075     notify->setPointer("buffer-id", info->mBufferID);
   3076 
   3077     info->mData->meta()->clear();
   3078     notify->setBuffer("buffer", info->mData);
   3079 
   3080     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
   3081     reply->setPointer("buffer-id", info->mBufferID);
   3082 
   3083     notify->setMessage("reply", reply);
   3084 
   3085     notify->post();
   3086 
   3087     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
   3088 }
   3089 
   3090 void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
   3091     IOMX::buffer_id bufferID;
   3092     CHECK(msg->findPointer("buffer-id", &bufferID));
   3093 
   3094     sp<ABuffer> buffer;
   3095     int32_t err = OK;
   3096     bool eos = false;
   3097     PortMode mode = getPortMode(kPortIndexInput);
   3098 
   3099     if (!msg->findBuffer("buffer", &buffer)) {
   3100         /* these are unfilled buffers returned by client */
   3101         CHECK(msg->findInt32("err", &err));
   3102 
   3103         if (err == OK) {
   3104             /* buffers with no errors are returned on MediaCodec.flush */
   3105             mode = KEEP_BUFFERS;
   3106         } else {
   3107             ALOGV("[%s] saw error %d instead of an input buffer",
   3108                  mCodec->mComponentName.c_str(), err);
   3109             eos = true;
   3110         }
   3111 
   3112         buffer.clear();
   3113     }
   3114 
   3115     int32_t tmp;
   3116     if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
   3117         eos = true;
   3118         err = ERROR_END_OF_STREAM;
   3119     }
   3120 
   3121     BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
   3122     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
   3123 
   3124     info->mStatus = BufferInfo::OWNED_BY_US;
   3125 
   3126     switch (mode) {
   3127         case KEEP_BUFFERS:
   3128         {
   3129             if (eos) {
   3130                 if (!mCodec->mPortEOS[kPortIndexInput]) {
   3131                     mCodec->mPortEOS[kPortIndexInput] = true;
   3132                     mCodec->mInputEOSResult = err;
   3133                 }
   3134             }
   3135             break;
   3136         }
   3137 
   3138         case RESUBMIT_BUFFERS:
   3139         {
   3140             if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
   3141                 int64_t timeUs;
   3142                 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
   3143 
   3144                 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
   3145 
   3146                 int32_t isCSD;
   3147                 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
   3148                     flags |= OMX_BUFFERFLAG_CODECCONFIG;
   3149                 }
   3150 
   3151                 if (eos) {
   3152                     flags |= OMX_BUFFERFLAG_EOS;
   3153                 }
   3154 
   3155                 if (buffer != info->mData) {
   3156                     ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
   3157                          mCodec->mComponentName.c_str(),
   3158                          bufferID,
   3159                          buffer.get(), info->mData.get());
   3160 
   3161                     CHECK_LE(buffer->size(), info->mData->capacity());
   3162                     memcpy(info->mData->data(), buffer->data(), buffer->size());
   3163                 }
   3164 
   3165                 if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
   3166                     ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
   3167                          mCodec->mComponentName.c_str(), bufferID);
   3168                 } else if (flags & OMX_BUFFERFLAG_EOS) {
   3169                     ALOGV("[%s] calling emptyBuffer %p w/ EOS",
   3170                          mCodec->mComponentName.c_str(), bufferID);
   3171                 } else {
   3172 #if TRACK_BUFFER_TIMING
   3173                     ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
   3174                          mCodec->mComponentName.c_str(), bufferID, timeUs);
   3175 #else
   3176                     ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
   3177                          mCodec->mComponentName.c_str(), bufferID, timeUs);
   3178 #endif
   3179                 }
   3180 
   3181 #if TRACK_BUFFER_TIMING
   3182                 ACodec::BufferStats stats;
   3183                 stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
   3184                 stats.mFillBufferDoneTimeUs = -1ll;
   3185                 mCodec->mBufferStats.add(timeUs, stats);
   3186 #endif
   3187 
   3188                 if (mCodec->mStoreMetaDataInOutputBuffers) {
   3189                     // try to submit an output buffer for each input buffer
   3190                     PortMode outputMode = getPortMode(kPortIndexOutput);
   3191 
   3192                     ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
   3193                             mCodec->mMetaDataBuffersToSubmit,
   3194                             (outputMode == FREE_BUFFERS ? "FREE" :
   3195                              outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
   3196                     if (outputMode == RESUBMIT_BUFFERS) {
   3197                         CHECK_EQ(mCodec->submitOutputMetaDataBuffer(),
   3198                                 (status_t)OK);
   3199                     }
   3200                 }
   3201 
   3202                 CHECK_EQ(mCodec->mOMX->emptyBuffer(
   3203                             mCodec->mNode,
   3204                             bufferID,
   3205                             0,
   3206                             buffer->size(),
   3207                             flags,
   3208                             timeUs),
   3209                          (status_t)OK);
   3210 
   3211                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
   3212 
   3213                 if (!eos) {
   3214                     getMoreInputDataIfPossible();
   3215                 } else {
   3216                     ALOGV("[%s] Signalled EOS on the input port",
   3217                          mCodec->mComponentName.c_str());
   3218 
   3219                     mCodec->mPortEOS[kPortIndexInput] = true;
   3220                     mCodec->mInputEOSResult = err;
   3221                 }
   3222             } else if (!mCodec->mPortEOS[kPortIndexInput]) {
   3223                 if (err != ERROR_END_OF_STREAM) {
   3224                     ALOGV("[%s] Signalling EOS on the input port "
   3225                          "due to error %d",
   3226                          mCodec->mComponentName.c_str(), err);
   3227                 } else {
   3228                     ALOGV("[%s] Signalling EOS on the input port",
   3229                          mCodec->mComponentName.c_str());
   3230                 }
   3231 
   3232                 ALOGV("[%s] calling emptyBuffer %p signalling EOS",
   3233                      mCodec->mComponentName.c_str(), bufferID);
   3234 
   3235                 CHECK_EQ(mCodec->mOMX->emptyBuffer(
   3236                             mCodec->mNode,
   3237                             bufferID,
   3238                             0,
   3239                             0,
   3240                             OMX_BUFFERFLAG_EOS,
   3241                             0),
   3242                          (status_t)OK);
   3243 
   3244                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
   3245 
   3246                 mCodec->mPortEOS[kPortIndexInput] = true;
   3247                 mCodec->mInputEOSResult = err;
   3248             }
   3249             break;
   3250 
   3251             default:
   3252                 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
   3253                 break;
   3254         }
   3255     }
   3256 }
   3257 
   3258 void ACodec::BaseState::getMoreInputDataIfPossible() {
   3259     if (mCodec->mPortEOS[kPortIndexInput]) {
   3260         return;
   3261     }
   3262 
   3263     BufferInfo *eligible = NULL;
   3264 
   3265     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
   3266         BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
   3267 
   3268 #if 0
   3269         if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
   3270             // There's already a "read" pending.
   3271             return;
   3272         }
   3273 #endif
   3274 
   3275         if (info->mStatus == BufferInfo::OWNED_BY_US) {
   3276             eligible = info;
   3277         }
   3278     }
   3279 
   3280     if (eligible == NULL) {
   3281         return;
   3282     }
   3283 
   3284     postFillThisBuffer(eligible);
   3285 }
   3286 
   3287 bool ACodec::BaseState::onOMXFillBufferDone(
   3288         IOMX::buffer_id bufferID,
   3289         size_t rangeOffset, size_t rangeLength,
   3290         OMX_U32 flags,
   3291         int64_t timeUs,
   3292         void *platformPrivate,
   3293         void *dataPtr) {
   3294     ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
   3295          mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
   3296 
   3297     ssize_t index;
   3298 
   3299 #if TRACK_BUFFER_TIMING
   3300     index = mCodec->mBufferStats.indexOfKey(timeUs);
   3301     if (index >= 0) {
   3302         ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
   3303         stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
   3304 
   3305         ALOGI("frame PTS %lld: %lld",
   3306                 timeUs,
   3307                 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
   3308 
   3309         mCodec->mBufferStats.removeItemsAt(index);
   3310         stats = NULL;
   3311     }
   3312 #endif
   3313 
   3314     BufferInfo *info =
   3315         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
   3316 
   3317     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
   3318 
   3319     info->mDequeuedAt = ++mCodec->mDequeueCounter;
   3320     info->mStatus = BufferInfo::OWNED_BY_US;
   3321 
   3322     PortMode mode = getPortMode(kPortIndexOutput);
   3323 
   3324     switch (mode) {
   3325         case KEEP_BUFFERS:
   3326             break;
   3327 
   3328         case RESUBMIT_BUFFERS:
   3329         {
   3330             if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
   3331                 ALOGV("[%s] calling fillBuffer %p",
   3332                      mCodec->mComponentName.c_str(), info->mBufferID);
   3333 
   3334                 CHECK_EQ(mCodec->mOMX->fillBuffer(
   3335                             mCodec->mNode, info->mBufferID),
   3336                          (status_t)OK);
   3337 
   3338                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
   3339                 break;
   3340             }
   3341 
   3342             sp<AMessage> reply =
   3343                 new AMessage(kWhatOutputBufferDrained, mCodec->id());
   3344 
   3345             if (!mCodec->mSentFormat) {
   3346                 mCodec->sendFormatChange(reply);
   3347             }
   3348 
   3349             if (mCodec->mUseMetadataOnEncoderOutput) {
   3350                 native_handle_t* handle =
   3351                         *(native_handle_t**)(info->mData->data() + 4);
   3352                 info->mData->meta()->setPointer("handle", handle);
   3353                 info->mData->meta()->setInt32("rangeOffset", rangeOffset);
   3354                 info->mData->meta()->setInt32("rangeLength", rangeLength);
   3355             } else {
   3356                 info->mData->setRange(rangeOffset, rangeLength);
   3357             }
   3358 #if 0
   3359             if (mCodec->mNativeWindow == NULL) {
   3360                 if (IsIDR(info->mData)) {
   3361                     ALOGI("IDR frame");
   3362                 }
   3363             }
   3364 #endif
   3365 
   3366             if (mCodec->mSkipCutBuffer != NULL) {
   3367                 mCodec->mSkipCutBuffer->submit(info->mData);
   3368             }
   3369             info->mData->meta()->setInt64("timeUs", timeUs);
   3370 
   3371             sp<AMessage> notify = mCodec->mNotify->dup();
   3372             notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
   3373             notify->setPointer("buffer-id", info->mBufferID);
   3374             notify->setBuffer("buffer", info->mData);
   3375             notify->setInt32("flags", flags);
   3376 
   3377             reply->setPointer("buffer-id", info->mBufferID);
   3378 
   3379             notify->setMessage("reply", reply);
   3380 
   3381             notify->post();
   3382 
   3383             info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
   3384 
   3385             if (flags & OMX_BUFFERFLAG_EOS) {
   3386                 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
   3387 
   3388                 sp<AMessage> notify = mCodec->mNotify->dup();
   3389                 notify->setInt32("what", ACodec::kWhatEOS);
   3390                 notify->setInt32("err", mCodec->mInputEOSResult);
   3391                 notify->post();
   3392 
   3393                 mCodec->mPortEOS[kPortIndexOutput] = true;
   3394             }
   3395             break;
   3396         }
   3397 
   3398         default:
   3399         {
   3400             CHECK_EQ((int)mode, (int)FREE_BUFFERS);
   3401 
   3402             CHECK_EQ((status_t)OK,
   3403                      mCodec->freeBuffer(kPortIndexOutput, index));
   3404             break;
   3405         }
   3406     }
   3407 
   3408     return true;
   3409 }
   3410 
   3411 void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
   3412     IOMX::buffer_id bufferID;
   3413     CHECK(msg->findPointer("buffer-id", &bufferID));
   3414 
   3415     ssize_t index;
   3416     BufferInfo *info =
   3417         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
   3418     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
   3419 
   3420     android_native_rect_t crop;
   3421     if (msg->findRect("crop",
   3422             &crop.left, &crop.top, &crop.right, &crop.bottom)) {
   3423         CHECK_EQ(0, native_window_set_crop(
   3424                 mCodec->mNativeWindow.get(), &crop));
   3425     }
   3426 
   3427     int32_t render;
   3428     if (mCodec->mNativeWindow != NULL
   3429             && msg->findInt32("render", &render) && render != 0
   3430             && (info->mData == NULL || info->mData->size() != 0)) {
   3431         // The client wants this buffer to be rendered.
   3432 
   3433         status_t err;
   3434         if ((err = mCodec->mNativeWindow->queueBuffer(
   3435                     mCodec->mNativeWindow.get(),
   3436                     info->mGraphicBuffer.get(), -1)) == OK) {
   3437             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
   3438         } else {
   3439             mCodec->signalError(OMX_ErrorUndefined, err);
   3440             info->mStatus = BufferInfo::OWNED_BY_US;
   3441         }
   3442     } else {
   3443         info->mStatus = BufferInfo::OWNED_BY_US;
   3444     }
   3445 
   3446     PortMode mode = getPortMode(kPortIndexOutput);
   3447 
   3448     switch (mode) {
   3449         case KEEP_BUFFERS:
   3450         {
   3451             // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
   3452 
   3453             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
   3454                 // We cannot resubmit the buffer we just rendered, dequeue
   3455                 // the spare instead.
   3456 
   3457                 info = mCodec->dequeueBufferFromNativeWindow();
   3458             }
   3459             break;
   3460         }
   3461 
   3462         case RESUBMIT_BUFFERS:
   3463         {
   3464             if (!mCodec->mPortEOS[kPortIndexOutput]) {
   3465                 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
   3466                     // We cannot resubmit the buffer we just rendered, dequeue
   3467                     // the spare instead.
   3468 
   3469                     info = mCodec->dequeueBufferFromNativeWindow();
   3470                 }
   3471 
   3472                 if (info != NULL) {
   3473                     ALOGV("[%s] calling fillBuffer %p",
   3474                          mCodec->mComponentName.c_str(), info->mBufferID);
   3475 
   3476                     CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
   3477                              (status_t)OK);
   3478 
   3479                     info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
   3480                 }
   3481             }
   3482             break;
   3483         }
   3484 
   3485         default:
   3486         {
   3487             CHECK_EQ((int)mode, (int)FREE_BUFFERS);
   3488 
   3489             CHECK_EQ((status_t)OK,
   3490                      mCodec->freeBuffer(kPortIndexOutput, index));
   3491             break;
   3492         }
   3493     }
   3494 }
   3495 
   3496 ////////////////////////////////////////////////////////////////////////////////
   3497 
   3498 ACodec::UninitializedState::UninitializedState(ACodec *codec)
   3499     : BaseState(codec) {
   3500 }
   3501 
   3502 void ACodec::UninitializedState::stateEntered() {
   3503     ALOGV("Now uninitialized");
   3504 
   3505     if (mDeathNotifier != NULL) {
   3506         mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
   3507         mDeathNotifier.clear();
   3508     }
   3509 
   3510     mCodec->mNativeWindow.clear();
   3511     mCodec->mNode = NULL;
   3512     mCodec->mOMX.clear();
   3513     mCodec->mQuirks = 0;
   3514     mCodec->mFlags = 0;
   3515     mCodec->mUseMetadataOnEncoderOutput = 0;
   3516     mCodec->mComponentName.clear();
   3517 }
   3518 
   3519 bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
   3520     bool handled = false;
   3521 
   3522     switch (msg->what()) {
   3523         case ACodec::kWhatSetup:
   3524         {
   3525             onSetup(msg);
   3526 
   3527             handled = true;
   3528             break;
   3529         }
   3530 
   3531         case ACodec::kWhatAllocateComponent:
   3532         {
   3533             onAllocateComponent(msg);
   3534             handled = true;
   3535             break;
   3536         }
   3537 
   3538         case ACodec::kWhatShutdown:
   3539         {
   3540             int32_t keepComponentAllocated;
   3541             CHECK(msg->findInt32(
   3542                         "keepComponentAllocated", &keepComponentAllocated));
   3543             CHECK(!keepComponentAllocated);
   3544 
   3545             sp<AMessage> notify = mCodec->mNotify->dup();
   3546             notify->setInt32("what", ACodec::kWhatShutdownCompleted);
   3547             notify->post();
   3548 
   3549             handled = true;
   3550             break;
   3551         }
   3552 
   3553         case ACodec::kWhatFlush:
   3554         {
   3555             sp<AMessage> notify = mCodec->mNotify->dup();
   3556             notify->setInt32("what", ACodec::kWhatFlushCompleted);
   3557             notify->post();
   3558 
   3559             handled = true;
   3560             break;
   3561         }
   3562 
   3563         default:
   3564             return BaseState::onMessageReceived(msg);
   3565     }
   3566 
   3567     return handled;
   3568 }
   3569 
   3570 void ACodec::UninitializedState::onSetup(
   3571         const sp<AMessage> &msg) {
   3572     if (onAllocateComponent(msg)
   3573             && mCodec->mLoadedState->onConfigureComponent(msg)) {
   3574         mCodec->mLoadedState->onStart();
   3575     }
   3576 }
   3577 
   3578 bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
   3579     ALOGV("onAllocateComponent");
   3580 
   3581     CHECK(mCodec->mNode == NULL);
   3582 
   3583     OMXClient client;
   3584     CHECK_EQ(client.connect(), (status_t)OK);
   3585 
   3586     sp<IOMX> omx = client.interface();
   3587 
   3588     sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
   3589 
   3590     mDeathNotifier = new DeathNotifier(notify);
   3591     if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
   3592         // This was a local binder, if it dies so do we, we won't care
   3593         // about any notifications in the afterlife.
   3594         mDeathNotifier.clear();
   3595     }
   3596 
   3597     Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
   3598 
   3599     AString mime;
   3600 
   3601     AString componentName;
   3602     uint32_t quirks = 0;
   3603     if (msg->findString("componentName", &componentName)) {
   3604         ssize_t index = matchingCodecs.add();
   3605         OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
   3606         entry->mName = String8(componentName.c_str());
   3607 
   3608         if (!OMXCodec::findCodecQuirks(
   3609                     componentName.c_str(), &entry->mQuirks)) {
   3610             entry->mQuirks = 0;
   3611         }
   3612     } else {
   3613         CHECK(msg->findString("mime", &mime));
   3614 
   3615         int32_t encoder;
   3616         if (!msg->findInt32("encoder", &encoder)) {
   3617             encoder = false;
   3618         }
   3619 
   3620         OMXCodec::findMatchingCodecs(
   3621                 mime.c_str(),
   3622                 encoder, // createEncoder
   3623                 NULL,  // matchComponentName
   3624                 0,     // flags
   3625                 &matchingCodecs);
   3626     }
   3627 
   3628     sp<CodecObserver> observer = new CodecObserver;
   3629     IOMX::node_id node = NULL;
   3630 
   3631     for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
   3632             ++matchIndex) {
   3633         componentName = matchingCodecs.itemAt(matchIndex).mName.string();
   3634         quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
   3635 
   3636         pid_t tid = androidGetTid();
   3637         int prevPriority = androidGetThreadPriority(tid);
   3638         androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
   3639         status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
   3640         androidSetThreadPriority(tid, prevPriority);
   3641 
   3642         if (err == OK) {
   3643             break;
   3644         }
   3645 
   3646         node = NULL;
   3647     }
   3648 
   3649     if (node == NULL) {
   3650         if (!mime.empty()) {
   3651             ALOGE("Unable to instantiate a decoder for type '%s'.",
   3652                  mime.c_str());
   3653         } else {
   3654             ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
   3655         }
   3656 
   3657         mCodec->signalError(OMX_ErrorComponentNotFound);
   3658         return false;
   3659     }
   3660 
   3661     notify = new AMessage(kWhatOMXMessage, mCodec->id());
   3662     observer->setNotificationMessage(notify);
   3663 
   3664     mCodec->mComponentName = componentName;
   3665     mCodec->mFlags = 0;
   3666 
   3667     if (componentName.endsWith(".secure")) {
   3668         mCodec->mFlags |= kFlagIsSecure;
   3669         mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
   3670     }
   3671 
   3672     mCodec->mQuirks = quirks;
   3673     mCodec->mOMX = omx;
   3674     mCodec->mNode = node;
   3675 
   3676     {
   3677         sp<AMessage> notify = mCodec->mNotify->dup();
   3678         notify->setInt32("what", ACodec::kWhatComponentAllocated);
   3679         notify->setString("componentName", mCodec->mComponentName.c_str());
   3680         notify->post();
   3681     }
   3682 
   3683     mCodec->changeState(mCodec->mLoadedState);
   3684 
   3685     return true;
   3686 }
   3687 
   3688 ////////////////////////////////////////////////////////////////////////////////
   3689 
   3690 ACodec::LoadedState::LoadedState(ACodec *codec)
   3691     : BaseState(codec) {
   3692 }
   3693 
   3694 void ACodec::LoadedState::stateEntered() {
   3695     ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
   3696 
   3697     mCodec->mPortEOS[kPortIndexInput] =
   3698         mCodec->mPortEOS[kPortIndexOutput] = false;
   3699 
   3700     mCodec->mInputEOSResult = OK;
   3701 
   3702     mCodec->mDequeueCounter = 0;
   3703     mCodec->mMetaDataBuffersToSubmit = 0;
   3704     mCodec->mRepeatFrameDelayUs = -1ll;
   3705 
   3706     if (mCodec->mShutdownInProgress) {
   3707         bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
   3708 
   3709         mCodec->mShutdownInProgress = false;
   3710         mCodec->mKeepComponentAllocated = false;
   3711 
   3712         onShutdown(keepComponentAllocated);
   3713     }
   3714 }
   3715 
   3716 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
   3717     if (!keepComponentAllocated) {
   3718         CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
   3719 
   3720         mCodec->changeState(mCodec->mUninitializedState);
   3721     }
   3722 
   3723     sp<AMessage> notify = mCodec->mNotify->dup();
   3724     notify->setInt32("what", ACodec::kWhatShutdownCompleted);
   3725     notify->post();
   3726 }
   3727 
   3728 bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
   3729     bool handled = false;
   3730 
   3731     switch (msg->what()) {
   3732         case ACodec::kWhatConfigureComponent:
   3733         {
   3734             onConfigureComponent(msg);
   3735             handled = true;
   3736             break;
   3737         }
   3738 
   3739         case ACodec::kWhatCreateInputSurface:
   3740         {
   3741             onCreateInputSurface(msg);
   3742             handled = true;
   3743             break;
   3744         }
   3745 
   3746         case ACodec::kWhatStart:
   3747         {
   3748             onStart();
   3749             handled = true;
   3750             break;
   3751         }
   3752 
   3753         case ACodec::kWhatShutdown:
   3754         {
   3755             int32_t keepComponentAllocated;
   3756             CHECK(msg->findInt32(
   3757                         "keepComponentAllocated", &keepComponentAllocated));
   3758 
   3759             onShutdown(keepComponentAllocated);
   3760 
   3761             handled = true;
   3762             break;
   3763         }
   3764 
   3765         case ACodec::kWhatFlush:
   3766         {
   3767             sp<AMessage> notify = mCodec->mNotify->dup();
   3768             notify->setInt32("what", ACodec::kWhatFlushCompleted);
   3769             notify->post();
   3770 
   3771             handled = true;
   3772             break;
   3773         }
   3774 
   3775         default:
   3776             return BaseState::onMessageReceived(msg);
   3777     }
   3778 
   3779     return handled;
   3780 }
   3781 
   3782 bool ACodec::LoadedState::onConfigureComponent(
   3783         const sp<AMessage> &msg) {
   3784     ALOGV("onConfigureComponent");
   3785 
   3786     CHECK(mCodec->mNode != NULL);
   3787 
   3788     AString mime;
   3789     CHECK(msg->findString("mime", &mime));
   3790 
   3791     status_t err = mCodec->configureCodec(mime.c_str(), msg);
   3792 
   3793     if (err != OK) {
   3794         ALOGE("[%s] configureCodec returning error %d",
   3795               mCodec->mComponentName.c_str(), err);
   3796 
   3797         mCodec->signalError(OMX_ErrorUndefined, err);
   3798         return false;
   3799     }
   3800 
   3801     sp<RefBase> obj;
   3802     if (msg->findObject("native-window", &obj)
   3803             && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
   3804         sp<NativeWindowWrapper> nativeWindow(
   3805                 static_cast<NativeWindowWrapper *>(obj.get()));
   3806         CHECK(nativeWindow != NULL);
   3807         mCodec->mNativeWindow = nativeWindow->getNativeWindow();
   3808 
   3809         native_window_set_scaling_mode(
   3810                 mCodec->mNativeWindow.get(),
   3811                 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
   3812     }
   3813     CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
   3814 
   3815     {
   3816         sp<AMessage> notify = mCodec->mNotify->dup();
   3817         notify->setInt32("what", ACodec::kWhatComponentConfigured);
   3818         notify->post();
   3819     }
   3820 
   3821     return true;
   3822 }
   3823 
   3824 void ACodec::LoadedState::onCreateInputSurface(
   3825         const sp<AMessage> &msg) {
   3826     ALOGV("onCreateInputSurface");
   3827 
   3828     sp<AMessage> notify = mCodec->mNotify->dup();
   3829     notify->setInt32("what", ACodec::kWhatInputSurfaceCreated);
   3830 
   3831     sp<IGraphicBufferProducer> bufferProducer;
   3832     status_t err;
   3833 
   3834     err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
   3835             &bufferProducer);
   3836 
   3837     if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
   3838         err = mCodec->mOMX->setInternalOption(
   3839                 mCodec->mNode,
   3840                 kPortIndexInput,
   3841                 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
   3842                 &mCodec->mRepeatFrameDelayUs,
   3843                 sizeof(mCodec->mRepeatFrameDelayUs));
   3844 
   3845         if (err != OK) {
   3846             ALOGE("[%s] Unable to configure option to repeat previous "
   3847                   "frames (err %d)",
   3848                   mCodec->mComponentName.c_str(),
   3849                   err);
   3850         }
   3851     }
   3852 
   3853     if (err == OK) {
   3854         notify->setObject("input-surface",
   3855                 new BufferProducerWrapper(bufferProducer));
   3856     } else {
   3857         // Can't use mCodec->signalError() here -- MediaCodec won't forward
   3858         // the error through because it's in the "configured" state.  We
   3859         // send a kWhatInputSurfaceCreated with an error value instead.
   3860         ALOGE("[%s] onCreateInputSurface returning error %d",
   3861                 mCodec->mComponentName.c_str(), err);
   3862         notify->setInt32("err", err);
   3863     }
   3864     notify->post();
   3865 }
   3866 
   3867 void ACodec::LoadedState::onStart() {
   3868     ALOGV("onStart");
   3869 
   3870     CHECK_EQ(mCodec->mOMX->sendCommand(
   3871                 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
   3872              (status_t)OK);
   3873 
   3874     mCodec->changeState(mCodec->mLoadedToIdleState);
   3875 }
   3876 
   3877 ////////////////////////////////////////////////////////////////////////////////
   3878 
   3879 ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
   3880     : BaseState(codec) {
   3881 }
   3882 
   3883 void ACodec::LoadedToIdleState::stateEntered() {
   3884     ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
   3885 
   3886     status_t err;
   3887     if ((err = allocateBuffers()) != OK) {
   3888         ALOGE("Failed to allocate buffers after transitioning to IDLE state "
   3889              "(error 0x%08x)",
   3890              err);
   3891 
   3892         mCodec->signalError(OMX_ErrorUndefined, err);
   3893 
   3894         mCodec->changeState(mCodec->mLoadedState);
   3895     }
   3896 }
   3897 
   3898 status_t ACodec::LoadedToIdleState::allocateBuffers() {
   3899     status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
   3900 
   3901     if (err != OK) {
   3902         return err;
   3903     }
   3904 
   3905     return mCodec->allocateBuffersOnPort(kPortIndexOutput);
   3906 }
   3907 
   3908 bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
   3909     switch (msg->what()) {
   3910         case kWhatShutdown:
   3911         {
   3912             mCodec->deferMessage(msg);
   3913             return true;
   3914         }
   3915 
   3916         case kWhatSignalEndOfInputStream:
   3917         {
   3918             mCodec->onSignalEndOfInputStream();
   3919             return true;
   3920         }
   3921 
   3922         case kWhatResume:
   3923         {
   3924             // We'll be active soon enough.
   3925             return true;
   3926         }
   3927 
   3928         case kWhatFlush:
   3929         {
   3930             // We haven't even started yet, so we're flushed alright...
   3931             sp<AMessage> notify = mCodec->mNotify->dup();
   3932             notify->setInt32("what", ACodec::kWhatFlushCompleted);
   3933             notify->post();
   3934             return true;
   3935         }
   3936 
   3937         default:
   3938             return BaseState::onMessageReceived(msg);
   3939     }
   3940 }
   3941 
   3942 bool ACodec::LoadedToIdleState::onOMXEvent(
   3943         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   3944     switch (event) {
   3945         case OMX_EventCmdComplete:
   3946         {
   3947             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
   3948             CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
   3949 
   3950             CHECK_EQ(mCodec->mOMX->sendCommand(
   3951                         mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
   3952                      (status_t)OK);
   3953 
   3954             mCodec->changeState(mCodec->mIdleToExecutingState);
   3955 
   3956             return true;
   3957         }
   3958 
   3959         default:
   3960             return BaseState::onOMXEvent(event, data1, data2);
   3961     }
   3962 }
   3963 
   3964 ////////////////////////////////////////////////////////////////////////////////
   3965 
   3966 ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
   3967     : BaseState(codec) {
   3968 }
   3969 
   3970 void ACodec::IdleToExecutingState::stateEntered() {
   3971     ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
   3972 }
   3973 
   3974 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
   3975     switch (msg->what()) {
   3976         case kWhatShutdown:
   3977         {
   3978             mCodec->deferMessage(msg);
   3979             return true;
   3980         }
   3981 
   3982         case kWhatResume:
   3983         {
   3984             // We'll be active soon enough.
   3985             return true;
   3986         }
   3987 
   3988         case kWhatFlush:
   3989         {
   3990             // We haven't even started yet, so we're flushed alright...
   3991             sp<AMessage> notify = mCodec->mNotify->dup();
   3992             notify->setInt32("what", ACodec::kWhatFlushCompleted);
   3993             notify->post();
   3994 
   3995             return true;
   3996         }
   3997 
   3998         case kWhatSignalEndOfInputStream:
   3999         {
   4000             mCodec->onSignalEndOfInputStream();
   4001             return true;
   4002         }
   4003 
   4004         default:
   4005             return BaseState::onMessageReceived(msg);
   4006     }
   4007 }
   4008 
   4009 bool ACodec::IdleToExecutingState::onOMXEvent(
   4010         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   4011     switch (event) {
   4012         case OMX_EventCmdComplete:
   4013         {
   4014             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
   4015             CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
   4016 
   4017             mCodec->mExecutingState->resume();
   4018             mCodec->changeState(mCodec->mExecutingState);
   4019 
   4020             return true;
   4021         }
   4022 
   4023         default:
   4024             return BaseState::onOMXEvent(event, data1, data2);
   4025     }
   4026 }
   4027 
   4028 ////////////////////////////////////////////////////////////////////////////////
   4029 
   4030 ACodec::ExecutingState::ExecutingState(ACodec *codec)
   4031     : BaseState(codec),
   4032       mActive(false) {
   4033 }
   4034 
   4035 ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
   4036         OMX_U32 portIndex) {
   4037     return RESUBMIT_BUFFERS;
   4038 }
   4039 
   4040 void ACodec::ExecutingState::submitOutputMetaBuffers() {
   4041     // submit as many buffers as there are input buffers with the codec
   4042     // in case we are in port reconfiguring
   4043     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
   4044         BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
   4045 
   4046         if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
   4047             if (mCodec->submitOutputMetaDataBuffer() != OK)
   4048                 break;
   4049         }
   4050     }
   4051 
   4052     // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
   4053     mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
   4054 }
   4055 
   4056 void ACodec::ExecutingState::submitRegularOutputBuffers() {
   4057     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
   4058         BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
   4059 
   4060         if (mCodec->mNativeWindow != NULL) {
   4061             CHECK(info->mStatus == BufferInfo::OWNED_BY_US
   4062                     || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
   4063 
   4064             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
   4065                 continue;
   4066             }
   4067         } else {
   4068             CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
   4069         }
   4070 
   4071         ALOGV("[%s] calling fillBuffer %p",
   4072              mCodec->mComponentName.c_str(), info->mBufferID);
   4073 
   4074         CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
   4075                  (status_t)OK);
   4076 
   4077         info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
   4078     }
   4079 }
   4080 
   4081 void ACodec::ExecutingState::submitOutputBuffers() {
   4082     submitRegularOutputBuffers();
   4083     if (mCodec->mStoreMetaDataInOutputBuffers) {
   4084         submitOutputMetaBuffers();
   4085     }
   4086 }
   4087 
   4088 void ACodec::ExecutingState::resume() {
   4089     if (mActive) {
   4090         ALOGV("[%s] We're already active, no need to resume.",
   4091              mCodec->mComponentName.c_str());
   4092 
   4093         return;
   4094     }
   4095 
   4096     submitOutputBuffers();
   4097 
   4098     // Post the first input buffer.
   4099     CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
   4100     BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
   4101 
   4102     postFillThisBuffer(info);
   4103 
   4104     mActive = true;
   4105 }
   4106 
   4107 void ACodec::ExecutingState::stateEntered() {
   4108     ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
   4109 
   4110     mCodec->processDeferredMessages();
   4111 }
   4112 
   4113 bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
   4114     bool handled = false;
   4115 
   4116     switch (msg->what()) {
   4117         case kWhatShutdown:
   4118         {
   4119             int32_t keepComponentAllocated;
   4120             CHECK(msg->findInt32(
   4121                         "keepComponentAllocated", &keepComponentAllocated));
   4122 
   4123             mCodec->mShutdownInProgress = true;
   4124             mCodec->mKeepComponentAllocated = keepComponentAllocated;
   4125 
   4126             mActive = false;
   4127 
   4128             CHECK_EQ(mCodec->mOMX->sendCommand(
   4129                         mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
   4130                      (status_t)OK);
   4131 
   4132             mCodec->changeState(mCodec->mExecutingToIdleState);
   4133 
   4134             handled = true;
   4135             break;
   4136         }
   4137 
   4138         case kWhatFlush:
   4139         {
   4140             ALOGV("[%s] ExecutingState flushing now "
   4141                  "(codec owns %d/%d input, %d/%d output).",
   4142                     mCodec->mComponentName.c_str(),
   4143                     mCodec->countBuffersOwnedByComponent(kPortIndexInput),
   4144                     mCodec->mBuffers[kPortIndexInput].size(),
   4145                     mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
   4146                     mCodec->mBuffers[kPortIndexOutput].size());
   4147 
   4148             mActive = false;
   4149 
   4150             CHECK_EQ(mCodec->mOMX->sendCommand(
   4151                         mCodec->mNode, OMX_CommandFlush, OMX_ALL),
   4152                      (status_t)OK);
   4153 
   4154             mCodec->changeState(mCodec->mFlushingState);
   4155             handled = true;
   4156             break;
   4157         }
   4158 
   4159         case kWhatResume:
   4160         {
   4161             resume();
   4162 
   4163             handled = true;
   4164             break;
   4165         }
   4166 
   4167         case kWhatRequestIDRFrame:
   4168         {
   4169             status_t err = mCodec->requestIDRFrame();
   4170             if (err != OK) {
   4171                 ALOGW("Requesting an IDR frame failed.");
   4172             }
   4173 
   4174             handled = true;
   4175             break;
   4176         }
   4177 
   4178         case kWhatSetParameters:
   4179         {
   4180             sp<AMessage> params;
   4181             CHECK(msg->findMessage("params", &params));
   4182 
   4183             status_t err = mCodec->setParameters(params);
   4184 
   4185             sp<AMessage> reply;
   4186             if (msg->findMessage("reply", &reply)) {
   4187                 reply->setInt32("err", err);
   4188                 reply->post();
   4189             }
   4190 
   4191             handled = true;
   4192             break;
   4193         }
   4194 
   4195         case ACodec::kWhatSignalEndOfInputStream:
   4196         {
   4197             mCodec->onSignalEndOfInputStream();
   4198             handled = true;
   4199             break;
   4200         }
   4201 
   4202         // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
   4203         case kWhatSubmitOutputMetaDataBufferIfEOS:
   4204         {
   4205             if (mCodec->mPortEOS[kPortIndexInput] &&
   4206                     !mCodec->mPortEOS[kPortIndexOutput]) {
   4207                 status_t err = mCodec->submitOutputMetaDataBuffer();
   4208                 if (err == OK) {
   4209                     mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
   4210                 }
   4211             }
   4212             return true;
   4213         }
   4214 
   4215         default:
   4216             handled = BaseState::onMessageReceived(msg);
   4217             break;
   4218     }
   4219 
   4220     return handled;
   4221 }
   4222 
   4223 status_t ACodec::setParameters(const sp<AMessage> &params) {
   4224     int32_t videoBitrate;
   4225     if (params->findInt32("video-bitrate", &videoBitrate)) {
   4226         OMX_VIDEO_CONFIG_BITRATETYPE configParams;
   4227         InitOMXParams(&configParams);
   4228         configParams.nPortIndex = kPortIndexOutput;
   4229         configParams.nEncodeBitrate = videoBitrate;
   4230 
   4231         status_t err = mOMX->setConfig(
   4232                 mNode,
   4233                 OMX_IndexConfigVideoBitrate,
   4234                 &configParams,
   4235                 sizeof(configParams));
   4236 
   4237         if (err != OK) {
   4238             ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
   4239                    videoBitrate, err);
   4240 
   4241             return err;
   4242         }
   4243     }
   4244 
   4245     int32_t dropInputFrames;
   4246     if (params->findInt32("drop-input-frames", &dropInputFrames)) {
   4247         bool suspend = dropInputFrames != 0;
   4248 
   4249         status_t err =
   4250             mOMX->setInternalOption(
   4251                      mNode,
   4252                      kPortIndexInput,
   4253                      IOMX::INTERNAL_OPTION_SUSPEND,
   4254                      &suspend,
   4255                      sizeof(suspend));
   4256 
   4257         if (err != OK) {
   4258             ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
   4259             return err;
   4260         }
   4261     }
   4262 
   4263     int32_t dummy;
   4264     if (params->findInt32("request-sync", &dummy)) {
   4265         status_t err = requestIDRFrame();
   4266 
   4267         if (err != OK) {
   4268             ALOGE("Requesting a sync frame failed w/ err %d", err);
   4269             return err;
   4270         }
   4271     }
   4272 
   4273     return OK;
   4274 }
   4275 
   4276 void ACodec::onSignalEndOfInputStream() {
   4277     sp<AMessage> notify = mNotify->dup();
   4278     notify->setInt32("what", ACodec::kWhatSignaledInputEOS);
   4279 
   4280     status_t err = mOMX->signalEndOfInputStream(mNode);
   4281     if (err != OK) {
   4282         notify->setInt32("err", err);
   4283     }
   4284     notify->post();
   4285 }
   4286 
   4287 bool ACodec::ExecutingState::onOMXEvent(
   4288         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   4289     switch (event) {
   4290         case OMX_EventPortSettingsChanged:
   4291         {
   4292             CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
   4293 
   4294             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
   4295                 mCodec->mMetaDataBuffersToSubmit = 0;
   4296                 CHECK_EQ(mCodec->mOMX->sendCommand(
   4297                             mCodec->mNode,
   4298                             OMX_CommandPortDisable, kPortIndexOutput),
   4299                          (status_t)OK);
   4300 
   4301                 mCodec->freeOutputBuffersNotOwnedByComponent();
   4302 
   4303                 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
   4304             } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
   4305                 mCodec->mSentFormat = false;
   4306             } else {
   4307                 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
   4308                      mCodec->mComponentName.c_str(), data2);
   4309             }
   4310 
   4311             return true;
   4312         }
   4313 
   4314         case OMX_EventBufferFlag:
   4315         {
   4316             return true;
   4317         }
   4318 
   4319         default:
   4320             return BaseState::onOMXEvent(event, data1, data2);
   4321     }
   4322 }
   4323 
   4324 ////////////////////////////////////////////////////////////////////////////////
   4325 
   4326 ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
   4327         ACodec *codec)
   4328     : BaseState(codec) {
   4329 }
   4330 
   4331 ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
   4332         OMX_U32 portIndex) {
   4333     if (portIndex == kPortIndexOutput) {
   4334         return FREE_BUFFERS;
   4335     }
   4336 
   4337     CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
   4338 
   4339     return RESUBMIT_BUFFERS;
   4340 }
   4341 
   4342 bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
   4343         const sp<AMessage> &msg) {
   4344     bool handled = false;
   4345 
   4346     switch (msg->what()) {
   4347         case kWhatFlush:
   4348         case kWhatShutdown:
   4349         case kWhatResume:
   4350         {
   4351             if (msg->what() == kWhatResume) {
   4352                 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
   4353             }
   4354 
   4355             mCodec->deferMessage(msg);
   4356             handled = true;
   4357             break;
   4358         }
   4359 
   4360         default:
   4361             handled = BaseState::onMessageReceived(msg);
   4362             break;
   4363     }
   4364 
   4365     return handled;
   4366 }
   4367 
   4368 void ACodec::OutputPortSettingsChangedState::stateEntered() {
   4369     ALOGV("[%s] Now handling output port settings change",
   4370          mCodec->mComponentName.c_str());
   4371 }
   4372 
   4373 bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
   4374         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   4375     switch (event) {
   4376         case OMX_EventCmdComplete:
   4377         {
   4378             if (data1 == (OMX_U32)OMX_CommandPortDisable) {
   4379                 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
   4380 
   4381                 ALOGV("[%s] Output port now disabled.",
   4382                         mCodec->mComponentName.c_str());
   4383 
   4384                 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
   4385                 mCodec->mDealer[kPortIndexOutput].clear();
   4386 
   4387                 CHECK_EQ(mCodec->mOMX->sendCommand(
   4388                             mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
   4389                          (status_t)OK);
   4390 
   4391                 status_t err;
   4392                 if ((err = mCodec->allocateBuffersOnPort(
   4393                                 kPortIndexOutput)) != OK) {
   4394                     ALOGE("Failed to allocate output port buffers after "
   4395                          "port reconfiguration (error 0x%08x)",
   4396                          err);
   4397 
   4398                     mCodec->signalError(OMX_ErrorUndefined, err);
   4399 
   4400                     // This is technically not correct, but appears to be
   4401                     // the only way to free the component instance.
   4402                     // Controlled transitioning from excecuting->idle
   4403                     // and idle->loaded seem impossible probably because
   4404                     // the output port never finishes re-enabling.
   4405                     mCodec->mShutdownInProgress = true;
   4406                     mCodec->mKeepComponentAllocated = false;
   4407                     mCodec->changeState(mCodec->mLoadedState);
   4408                 }
   4409 
   4410                 return true;
   4411             } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
   4412                 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
   4413 
   4414                 mCodec->mSentFormat = false;
   4415 
   4416                 ALOGV("[%s] Output port now reenabled.",
   4417                         mCodec->mComponentName.c_str());
   4418 
   4419                 if (mCodec->mExecutingState->active()) {
   4420                     mCodec->mExecutingState->submitOutputBuffers();
   4421                 }
   4422 
   4423                 mCodec->changeState(mCodec->mExecutingState);
   4424 
   4425                 return true;
   4426             }
   4427 
   4428             return false;
   4429         }
   4430 
   4431         default:
   4432             return false;
   4433     }
   4434 }
   4435 
   4436 ////////////////////////////////////////////////////////////////////////////////
   4437 
   4438 ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
   4439     : BaseState(codec),
   4440       mComponentNowIdle(false) {
   4441 }
   4442 
   4443 bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
   4444     bool handled = false;
   4445 
   4446     switch (msg->what()) {
   4447         case kWhatFlush:
   4448         {
   4449             // Don't send me a flush request if you previously wanted me
   4450             // to shutdown.
   4451             TRESPASS();
   4452             break;
   4453         }
   4454 
   4455         case kWhatShutdown:
   4456         {
   4457             // We're already doing that...
   4458 
   4459             handled = true;
   4460             break;
   4461         }
   4462 
   4463         default:
   4464             handled = BaseState::onMessageReceived(msg);
   4465             break;
   4466     }
   4467 
   4468     return handled;
   4469 }
   4470 
   4471 void ACodec::ExecutingToIdleState::stateEntered() {
   4472     ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
   4473 
   4474     mComponentNowIdle = false;
   4475     mCodec->mSentFormat = false;
   4476 }
   4477 
   4478 bool ACodec::ExecutingToIdleState::onOMXEvent(
   4479         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   4480     switch (event) {
   4481         case OMX_EventCmdComplete:
   4482         {
   4483             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
   4484             CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
   4485 
   4486             mComponentNowIdle = true;
   4487 
   4488             changeStateIfWeOwnAllBuffers();
   4489 
   4490             return true;
   4491         }
   4492 
   4493         case OMX_EventPortSettingsChanged:
   4494         case OMX_EventBufferFlag:
   4495         {
   4496             // We're shutting down and don't care about this anymore.
   4497             return true;
   4498         }
   4499 
   4500         default:
   4501             return BaseState::onOMXEvent(event, data1, data2);
   4502     }
   4503 }
   4504 
   4505 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
   4506     if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
   4507         CHECK_EQ(mCodec->mOMX->sendCommand(
   4508                     mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
   4509                  (status_t)OK);
   4510 
   4511         CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
   4512         CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
   4513 
   4514         if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
   4515                 && mCodec->mNativeWindow != NULL) {
   4516             // We push enough 1x1 blank buffers to ensure that one of
   4517             // them has made it to the display.  This allows the OMX
   4518             // component teardown to zero out any protected buffers
   4519             // without the risk of scanning out one of those buffers.
   4520             mCodec->pushBlankBuffersToNativeWindow();
   4521         }
   4522 
   4523         mCodec->changeState(mCodec->mIdleToLoadedState);
   4524     }
   4525 }
   4526 
   4527 void ACodec::ExecutingToIdleState::onInputBufferFilled(
   4528         const sp<AMessage> &msg) {
   4529     BaseState::onInputBufferFilled(msg);
   4530 
   4531     changeStateIfWeOwnAllBuffers();
   4532 }
   4533 
   4534 void ACodec::ExecutingToIdleState::onOutputBufferDrained(
   4535         const sp<AMessage> &msg) {
   4536     BaseState::onOutputBufferDrained(msg);
   4537 
   4538     changeStateIfWeOwnAllBuffers();
   4539 }
   4540 
   4541 ////////////////////////////////////////////////////////////////////////////////
   4542 
   4543 ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
   4544     : BaseState(codec) {
   4545 }
   4546 
   4547 bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
   4548     bool handled = false;
   4549 
   4550     switch (msg->what()) {
   4551         case kWhatShutdown:
   4552         {
   4553             // We're already doing that...
   4554 
   4555             handled = true;
   4556             break;
   4557         }
   4558 
   4559         case kWhatFlush:
   4560         {
   4561             // Don't send me a flush request if you previously wanted me
   4562             // to shutdown.
   4563             TRESPASS();
   4564             break;
   4565         }
   4566 
   4567         default:
   4568             handled = BaseState::onMessageReceived(msg);
   4569             break;
   4570     }
   4571 
   4572     return handled;
   4573 }
   4574 
   4575 void ACodec::IdleToLoadedState::stateEntered() {
   4576     ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
   4577 }
   4578 
   4579 bool ACodec::IdleToLoadedState::onOMXEvent(
   4580         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   4581     switch (event) {
   4582         case OMX_EventCmdComplete:
   4583         {
   4584             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
   4585             CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
   4586 
   4587             mCodec->changeState(mCodec->mLoadedState);
   4588 
   4589             return true;
   4590         }
   4591 
   4592         default:
   4593             return BaseState::onOMXEvent(event, data1, data2);
   4594     }
   4595 }
   4596 
   4597 ////////////////////////////////////////////////////////////////////////////////
   4598 
   4599 ACodec::FlushingState::FlushingState(ACodec *codec)
   4600     : BaseState(codec) {
   4601 }
   4602 
   4603 void ACodec::FlushingState::stateEntered() {
   4604     ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
   4605 
   4606     mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
   4607 }
   4608 
   4609 bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
   4610     bool handled = false;
   4611 
   4612     switch (msg->what()) {
   4613         case kWhatShutdown:
   4614         {
   4615             mCodec->deferMessage(msg);
   4616             break;
   4617         }
   4618 
   4619         case kWhatFlush:
   4620         {
   4621             // We're already doing this right now.
   4622             handled = true;
   4623             break;
   4624         }
   4625 
   4626         default:
   4627             handled = BaseState::onMessageReceived(msg);
   4628             break;
   4629     }
   4630 
   4631     return handled;
   4632 }
   4633 
   4634 bool ACodec::FlushingState::onOMXEvent(
   4635         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   4636     ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
   4637             mCodec->mComponentName.c_str(), event, data1);
   4638 
   4639     switch (event) {
   4640         case OMX_EventCmdComplete:
   4641         {
   4642             CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
   4643 
   4644             if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
   4645                 CHECK(!mFlushComplete[data2]);
   4646                 mFlushComplete[data2] = true;
   4647 
   4648                 if (mFlushComplete[kPortIndexInput]
   4649                         && mFlushComplete[kPortIndexOutput]) {
   4650                     changeStateIfWeOwnAllBuffers();
   4651                 }
   4652             } else {
   4653                 CHECK_EQ(data2, OMX_ALL);
   4654                 CHECK(mFlushComplete[kPortIndexInput]);
   4655                 CHECK(mFlushComplete[kPortIndexOutput]);
   4656 
   4657                 changeStateIfWeOwnAllBuffers();
   4658             }
   4659 
   4660             return true;
   4661         }
   4662 
   4663         case OMX_EventPortSettingsChanged:
   4664         {
   4665             sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
   4666             msg->setInt32("type", omx_message::EVENT);
   4667             msg->setPointer("node", mCodec->mNode);
   4668             msg->setInt32("event", event);
   4669             msg->setInt32("data1", data1);
   4670             msg->setInt32("data2", data2);
   4671 
   4672             ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
   4673                  mCodec->mComponentName.c_str());
   4674 
   4675             mCodec->deferMessage(msg);
   4676 
   4677             return true;
   4678         }
   4679 
   4680         default:
   4681             return BaseState::onOMXEvent(event, data1, data2);
   4682     }
   4683 
   4684     return true;
   4685 }
   4686 
   4687 void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
   4688     BaseState::onOutputBufferDrained(msg);
   4689 
   4690     changeStateIfWeOwnAllBuffers();
   4691 }
   4692 
   4693 void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
   4694     BaseState::onInputBufferFilled(msg);
   4695 
   4696     changeStateIfWeOwnAllBuffers();
   4697 }
   4698 
   4699 void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
   4700     if (mFlushComplete[kPortIndexInput]
   4701             && mFlushComplete[kPortIndexOutput]
   4702             && mCodec->allYourBuffersAreBelongToUs()) {
   4703         // We now own all buffers except possibly those still queued with
   4704         // the native window for rendering. Let's get those back as well.
   4705         mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
   4706 
   4707         sp<AMessage> notify = mCodec->mNotify->dup();
   4708         notify->setInt32("what", ACodec::kWhatFlushCompleted);
   4709         notify->post();
   4710 
   4711         mCodec->mPortEOS[kPortIndexInput] =
   4712             mCodec->mPortEOS[kPortIndexOutput] = false;
   4713 
   4714         mCodec->mInputEOSResult = OK;
   4715 
   4716         if (mCodec->mSkipCutBuffer != NULL) {
   4717             mCodec->mSkipCutBuffer->clear();
   4718         }
   4719 
   4720         mCodec->changeState(mCodec->mExecutingState);
   4721     }
   4722 }
   4723 
   4724 }  // namespace android
   4725