Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "MediaFilter"
     19 
     20 #include <inttypes.h>
     21 #include <utils/Trace.h>
     22 
     23 #include <binder/MemoryDealer.h>
     24 
     25 #include <media/stagefright/BufferProducerWrapper.h>
     26 #include <media/stagefright/foundation/ABuffer.h>
     27 #include <media/stagefright/foundation/ADebug.h>
     28 #include <media/stagefright/foundation/AMessage.h>
     29 
     30 #include <media/stagefright/MediaDefs.h>
     31 #include <media/stagefright/MediaErrors.h>
     32 #include <media/stagefright/MediaFilter.h>
     33 
     34 #include <media/MediaCodecBuffer.h>
     35 
     36 #include <gui/BufferItem.h>
     37 
     38 #include "ColorConvert.h"
     39 #include "GraphicBufferListener.h"
     40 #include "IntrinsicBlurFilter.h"
     41 #include "RSFilter.h"
     42 #include "SaturationFilter.h"
     43 #include "ZeroFilter.h"
     44 
     45 #include "../include/ACodecBufferChannel.h"
     46 #include "../include/SharedMemoryBuffer.h"
     47 
     48 namespace android {
     49 
     50 // parameter: number of input and output buffers
     51 static const size_t kBufferCountActual = 4;
     52 
     53 MediaFilter::MediaFilter()
     54     : mState(UNINITIALIZED),
     55       mGeneration(0),
     56       mGraphicBufferListener(NULL) {
     57     mBufferChannel = std::make_shared<ACodecBufferChannel>(
     58             new AMessage(kWhatInputBufferFilled, this),
     59             new AMessage(kWhatOutputBufferDrained, this));
     60 }
     61 
     62 MediaFilter::~MediaFilter() {
     63 }
     64 
     65 //////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
     66 
     67 std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
     68     return mBufferChannel;
     69 }
     70 
     71 void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) {
     72     msg->setWhat(kWhatAllocateComponent);
     73     msg->setTarget(this);
     74     msg->post();
     75 }
     76 
     77 void MediaFilter::initiateConfigureComponent(const sp<AMessage> &msg) {
     78     msg->setWhat(kWhatConfigureComponent);
     79     msg->setTarget(this);
     80     msg->post();
     81 }
     82 
     83 void MediaFilter::initiateCreateInputSurface() {
     84     (new AMessage(kWhatCreateInputSurface, this))->post();
     85 }
     86 
     87 void MediaFilter::initiateSetInputSurface(
     88         const sp<PersistentSurface> & /* surface */) {
     89     ALOGW("initiateSetInputSurface() unsupported");
     90 }
     91 
     92 void MediaFilter::initiateStart() {
     93     (new AMessage(kWhatStart, this))->post();
     94 }
     95 
     96 void MediaFilter::initiateShutdown(bool keepComponentAllocated) {
     97     sp<AMessage> msg = new AMessage(kWhatShutdown, this);
     98     msg->setInt32("keepComponentAllocated", keepComponentAllocated);
     99     msg->post();
    100 }
    101 
    102 void MediaFilter::signalFlush() {
    103     (new AMessage(kWhatFlush, this))->post();
    104 }
    105 
    106 void MediaFilter::signalResume() {
    107     (new AMessage(kWhatResume, this))->post();
    108 }
    109 
    110 // nothing to do
    111 void MediaFilter::signalRequestIDRFrame() {
    112     return;
    113 }
    114 
    115 void MediaFilter::signalSetParameters(const sp<AMessage> &params) {
    116     sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
    117     msg->setMessage("params", params);
    118     msg->post();
    119 }
    120 
    121 void MediaFilter::signalEndOfInputStream() {
    122     (new AMessage(kWhatSignalEndOfInputStream, this))->post();
    123 }
    124 
    125 void MediaFilter::onMessageReceived(const sp<AMessage> &msg) {
    126     switch (msg->what()) {
    127         case kWhatAllocateComponent:
    128         {
    129             onAllocateComponent(msg);
    130             break;
    131         }
    132         case kWhatConfigureComponent:
    133         {
    134             onConfigureComponent(msg);
    135             break;
    136         }
    137         case kWhatStart:
    138         {
    139             onStart();
    140             break;
    141         }
    142         case kWhatProcessBuffers:
    143         {
    144             processBuffers();
    145             break;
    146         }
    147         case kWhatInputBufferFilled:
    148         {
    149             onInputBufferFilled(msg);
    150             break;
    151         }
    152         case kWhatOutputBufferDrained:
    153         {
    154             onOutputBufferDrained(msg);
    155             break;
    156         }
    157         case kWhatShutdown:
    158         {
    159             onShutdown(msg);
    160             break;
    161         }
    162         case kWhatFlush:
    163         {
    164             onFlush();
    165             break;
    166         }
    167         case kWhatResume:
    168         {
    169             // nothing to do
    170             break;
    171         }
    172         case kWhatSetParameters:
    173         {
    174             onSetParameters(msg);
    175             break;
    176         }
    177         case kWhatCreateInputSurface:
    178         {
    179             onCreateInputSurface();
    180             break;
    181         }
    182         case GraphicBufferListener::kWhatFrameAvailable:
    183         {
    184             onInputFrameAvailable();
    185             break;
    186         }
    187         case kWhatSignalEndOfInputStream:
    188         {
    189             onSignalEndOfInputStream();
    190             break;
    191         }
    192         default:
    193         {
    194             ALOGE("Message not handled:\n%s", msg->debugString().c_str());
    195             break;
    196         }
    197     }
    198 }
    199 
    200 //////////////////// HELPER FUNCTIONS //////////////////////////////////////////
    201 
    202 void MediaFilter::signalProcessBuffers() {
    203     (new AMessage(kWhatProcessBuffers, this))->post();
    204 }
    205 
    206 void MediaFilter::signalError(status_t error) {
    207     mCallback->onError(error, ACTION_CODE_FATAL);
    208 }
    209 
    210 status_t MediaFilter::allocateBuffersOnPort(OMX_U32 portIndex) {
    211     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
    212     const bool isInput = portIndex == kPortIndexInput;
    213     const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize;
    214 
    215     CHECK(mDealer[portIndex] == NULL);
    216     CHECK(mBuffers[portIndex].isEmpty());
    217 
    218     ALOGV("Allocating %zu buffers of size %zu on %s port",
    219             kBufferCountActual, bufferSize,
    220             isInput ? "input" : "output");
    221 
    222     size_t totalSize = kBufferCountActual * bufferSize;
    223 
    224     mDealer[portIndex] = new MemoryDealer(totalSize, "MediaFilter");
    225 
    226     for (size_t i = 0; i < kBufferCountActual; ++i) {
    227         sp<IMemory> mem = mDealer[portIndex]->allocate(bufferSize);
    228         CHECK(mem.get() != NULL);
    229 
    230         BufferInfo info;
    231         info.mStatus = BufferInfo::OWNED_BY_US;
    232         info.mBufferID = i;
    233         info.mGeneration = mGeneration;
    234         info.mOutputFlags = 0;
    235         info.mData = new SharedMemoryBuffer(
    236                 isInput ? mInputFormat : mOutputFormat, mem);
    237         info.mData->meta()->setInt64("timeUs", 0);
    238 
    239         mBuffers[portIndex].push_back(info);
    240 
    241         if (!isInput) {
    242             mAvailableOutputBuffers.push(
    243                     &mBuffers[portIndex].editItemAt(i));
    244         }
    245     }
    246 
    247     std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
    248     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
    249         array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
    250     }
    251     if (portIndex == kPortIndexInput) {
    252         mBufferChannel->setInputBufferArray(array);
    253     } else {
    254         mBufferChannel->setOutputBufferArray(array);
    255     }
    256 
    257     return OK;
    258 }
    259 
    260 MediaFilter::BufferInfo* MediaFilter::findBufferByID(
    261         uint32_t portIndex, IOMX::buffer_id bufferID,
    262         ssize_t *index) {
    263     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
    264         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
    265 
    266         if (info->mBufferID == bufferID) {
    267             if (index != NULL) {
    268                 *index = i;
    269             }
    270             return info;
    271         }
    272     }
    273 
    274     TRESPASS();
    275 
    276     return NULL;
    277 }
    278 
    279 void MediaFilter::postFillThisBuffer(BufferInfo *info) {
    280     ALOGV("postFillThisBuffer on buffer %d", info->mBufferID);
    281     if (mPortEOS[kPortIndexInput]) {
    282         return;
    283     }
    284 
    285     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
    286 
    287     info->mGeneration = mGeneration;
    288 
    289     info->mData->meta()->clear();
    290 
    291     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
    292     reply->setInt32("buffer-id", info->mBufferID);
    293 
    294     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
    295 
    296     mBufferChannel->fillThisBuffer(info->mBufferID);
    297 }
    298 
    299 void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
    300     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
    301 
    302     info->mGeneration = mGeneration;
    303 
    304     sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
    305     reply->setInt32("buffer-id", info->mBufferID);
    306 
    307     mBufferChannel->drainThisBuffer(info->mBufferID, info->mOutputFlags);
    308 
    309     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
    310 }
    311 
    312 void MediaFilter::postEOS() {
    313     mCallback->onEos(ERROR_END_OF_STREAM);
    314 
    315     ALOGV("Sent kWhatEOS.");
    316 }
    317 
    318 void MediaFilter::requestFillEmptyInput() {
    319     if (mPortEOS[kPortIndexInput]) {
    320         return;
    321     }
    322 
    323     for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
    324         BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
    325 
    326         if (info->mStatus == BufferInfo::OWNED_BY_US) {
    327             postFillThisBuffer(info);
    328         }
    329     }
    330 }
    331 
    332 void MediaFilter::processBuffers() {
    333     if (mAvailableInputBuffers.empty() || mAvailableOutputBuffers.empty()) {
    334         ALOGV("Skipping process (buffers unavailable)");
    335         return;
    336     }
    337 
    338     if (mPortEOS[kPortIndexOutput]) {
    339         // TODO notify caller of queueInput error when it is supported
    340         // in MediaCodec
    341         ALOGW("Tried to process a buffer after EOS.");
    342         return;
    343     }
    344 
    345     BufferInfo *inputInfo = mAvailableInputBuffers[0];
    346     mAvailableInputBuffers.removeAt(0);
    347     BufferInfo *outputInfo = mAvailableOutputBuffers[0];
    348     mAvailableOutputBuffers.removeAt(0);
    349 
    350     status_t err;
    351     err = mFilter->processBuffers(inputInfo->mData, outputInfo->mData);
    352     if (err != (status_t)OK) {
    353         outputInfo->mData->meta()->setInt32("err", err);
    354     }
    355 
    356     int64_t timeUs;
    357     CHECK(inputInfo->mData->meta()->findInt64("timeUs", &timeUs));
    358     outputInfo->mData->meta()->setInt64("timeUs", timeUs);
    359     outputInfo->mOutputFlags = 0;
    360     int32_t eos = 0;
    361     if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) {
    362         outputInfo->mOutputFlags |= OMX_BUFFERFLAG_EOS;
    363         mPortEOS[kPortIndexOutput] = true;
    364         outputInfo->mData->meta()->setInt32("eos", eos);
    365         postEOS();
    366         ALOGV("Output stream saw EOS.");
    367     }
    368 
    369     ALOGV("Processed input buffer %u [%zu], output buffer %u [%zu]",
    370                 inputInfo->mBufferID, inputInfo->mData->size(),
    371                 outputInfo->mBufferID, outputInfo->mData->size());
    372 
    373     if (mGraphicBufferListener != NULL) {
    374         delete inputInfo;
    375     } else {
    376         postFillThisBuffer(inputInfo);
    377     }
    378     postDrainThisBuffer(outputInfo);
    379 
    380     // prevent any corner case where buffers could get stuck in queue
    381     signalProcessBuffers();
    382 }
    383 
    384 void MediaFilter::onAllocateComponent(const sp<AMessage> &msg) {
    385     CHECK_EQ(mState, UNINITIALIZED);
    386 
    387     CHECK(msg->findString("componentName", &mComponentName));
    388     const char* name = mComponentName.c_str();
    389     if (!strcasecmp(name, "android.filter.zerofilter")) {
    390         mFilter = new ZeroFilter;
    391     } else if (!strcasecmp(name, "android.filter.saturation")) {
    392         mFilter = new SaturationFilter;
    393     } else if (!strcasecmp(name, "android.filter.intrinsicblur")) {
    394         mFilter = new IntrinsicBlurFilter;
    395     } else if (!strcasecmp(name, "android.filter.RenderScript")) {
    396         mFilter = new RSFilter;
    397     } else {
    398         ALOGE("Unrecognized filter name: %s", name);
    399         signalError(NAME_NOT_FOUND);
    400         return;
    401     }
    402 
    403     // HACK - need "OMX.google" to use MediaCodec's software renderer
    404     mCallback->onComponentAllocated("OMX.google.MediaFilter");
    405     mState = INITIALIZED;
    406     ALOGV("Handled kWhatAllocateComponent.");
    407 }
    408 
    409 void MediaFilter::onConfigureComponent(const sp<AMessage> &msg) {
    410     // TODO: generalize to allow audio filters as well as video
    411 
    412     CHECK_EQ(mState, INITIALIZED);
    413 
    414     // get params - at least mime, width & height
    415     AString mime;
    416     CHECK(msg->findString("mime", &mime));
    417     if (strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
    418         ALOGE("Bad mime: %s", mime.c_str());
    419         signalError(BAD_VALUE);
    420         return;
    421     }
    422 
    423     CHECK(msg->findInt32("width", &mWidth));
    424     CHECK(msg->findInt32("height", &mHeight));
    425     if (!msg->findInt32("stride", &mStride)) {
    426         mStride = mWidth;
    427     }
    428     if (!msg->findInt32("slice-height", &mSliceHeight)) {
    429         mSliceHeight = mHeight;
    430     }
    431 
    432     mMaxInputSize = mWidth * mHeight * 4;   // room for ARGB8888
    433     int32_t maxInputSize;
    434     if (msg->findInt32("max-input-size", &maxInputSize)
    435             && (size_t)maxInputSize > mMaxInputSize) {
    436         mMaxInputSize = maxInputSize;
    437     }
    438 
    439     if (!msg->findInt32("color-format", &mColorFormatIn)) {
    440         // default to OMX_COLOR_Format32bitARGB8888
    441         mColorFormatIn = OMX_COLOR_Format32bitARGB8888;
    442         msg->setInt32("color-format", mColorFormatIn);
    443     }
    444     mColorFormatOut = mColorFormatIn;
    445 
    446     mMaxOutputSize = mWidth * mHeight * 4;  // room for ARGB8888
    447 
    448     AString cacheDir;
    449     if (!msg->findString("cacheDir", &cacheDir)) {
    450         ALOGE("Failed to find cache directory in config message.");
    451         signalError(NAME_NOT_FOUND);
    452         return;
    453     }
    454 
    455     status_t err;
    456     err = mFilter->configure(msg);
    457     if (err != (status_t)OK) {
    458         ALOGE("Failed to configure filter component, err %d", err);
    459         signalError(err);
    460         return;
    461     }
    462 
    463     mInputFormat = new AMessage();
    464     mInputFormat->setString("mime", mime.c_str());
    465     mInputFormat->setInt32("stride", mStride);
    466     mInputFormat->setInt32("slice-height", mSliceHeight);
    467     mInputFormat->setInt32("color-format", mColorFormatIn);
    468     mInputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
    469     mInputFormat->setInt32("width", mWidth);
    470     mInputFormat->setInt32("height", mHeight);
    471 
    472     mOutputFormat = new AMessage();
    473     mOutputFormat->setString("mime", mime.c_str());
    474     mOutputFormat->setInt32("stride", mStride);
    475     mOutputFormat->setInt32("slice-height", mSliceHeight);
    476     mOutputFormat->setInt32("color-format", mColorFormatOut);
    477     mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
    478     mOutputFormat->setInt32("width", mWidth);
    479     mOutputFormat->setInt32("height", mHeight);
    480 
    481     mCallback->onComponentConfigured(mInputFormat, mOutputFormat);
    482     mState = CONFIGURED;
    483     ALOGV("Handled kWhatConfigureComponent.");
    484 }
    485 
    486 void MediaFilter::onStart() {
    487     CHECK_EQ(mState, CONFIGURED);
    488 
    489     allocateBuffersOnPort(kPortIndexInput);
    490 
    491     allocateBuffersOnPort(kPortIndexOutput);
    492 
    493     mCallback->onStartCompleted();
    494 
    495     status_t err = mFilter->start();
    496     if (err != (status_t)OK) {
    497         ALOGE("Failed to start filter component, err %d", err);
    498         signalError(err);
    499         return;
    500     }
    501 
    502     mPortEOS[kPortIndexInput] = false;
    503     mPortEOS[kPortIndexOutput] = false;
    504     mInputEOSResult = OK;
    505     mState = STARTED;
    506 
    507     requestFillEmptyInput();
    508     ALOGV("Handled kWhatStart.");
    509 }
    510 
    511 void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
    512     IOMX::buffer_id bufferID;
    513     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
    514     BufferInfo *info = findBufferByID(kPortIndexInput, bufferID);
    515 
    516     if (mState != STARTED) {
    517         // we're not running, so we'll just keep that buffer...
    518         info->mStatus = BufferInfo::OWNED_BY_US;
    519         return;
    520     }
    521 
    522     if (info->mGeneration != mGeneration) {
    523         ALOGV("Caught a stale input buffer [ID %d]", bufferID);
    524         // buffer is stale (taken before a flush/shutdown) - repost it
    525         CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
    526         postFillThisBuffer(info);
    527         return;
    528     }
    529 
    530     CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
    531     info->mStatus = BufferInfo::OWNED_BY_US;
    532 
    533     sp<MediaCodecBuffer> buffer;
    534     int32_t err = OK;
    535     bool eos = false;
    536 
    537     sp<RefBase> obj;
    538     if (!msg->findObject("buffer", &obj)) {
    539         // these are unfilled buffers returned by client
    540         CHECK(msg->findInt32("err", &err));
    541 
    542         if (err == OK) {
    543             // buffers with no errors are returned on MediaCodec.flush
    544             ALOGV("saw unfilled buffer (MediaCodec.flush)");
    545             postFillThisBuffer(info);
    546             return;
    547         } else {
    548             ALOGV("saw error %d instead of an input buffer", err);
    549             eos = true;
    550         }
    551 
    552         buffer.clear();
    553     } else {
    554         buffer = static_cast<MediaCodecBuffer *>(obj.get());
    555     }
    556 
    557     int32_t isCSD;
    558     if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
    559             && isCSD != 0) {
    560         // ignore codec-specific data buffers
    561         ALOGW("MediaFilter received a codec-specific data buffer");
    562         postFillThisBuffer(info);
    563         return;
    564     }
    565 
    566     int32_t tmp;
    567     if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
    568         eos = true;
    569         err = ERROR_END_OF_STREAM;
    570     }
    571 
    572     mAvailableInputBuffers.push_back(info);
    573     processBuffers();
    574 
    575     if (eos) {
    576         mPortEOS[kPortIndexInput] = true;
    577         mInputEOSResult = err;
    578     }
    579 
    580     ALOGV("Handled kWhatInputBufferFilled. [ID %u]", bufferID);
    581 }
    582 
    583 void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
    584     IOMX::buffer_id bufferID;
    585     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
    586     BufferInfo *info = findBufferByID(kPortIndexOutput, bufferID);
    587 
    588     if (mState != STARTED) {
    589         // we're not running, so we'll just keep that buffer...
    590         info->mStatus = BufferInfo::OWNED_BY_US;
    591         return;
    592     }
    593 
    594     if (info->mGeneration != mGeneration) {
    595         ALOGV("Caught a stale output buffer [ID %d]", bufferID);
    596         // buffer is stale (taken before a flush/shutdown) - keep it
    597         CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
    598         return;
    599     }
    600 
    601     CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
    602     info->mStatus = BufferInfo::OWNED_BY_US;
    603 
    604     mAvailableOutputBuffers.push_back(info);
    605 
    606     processBuffers();
    607 
    608     ALOGV("Handled kWhatOutputBufferDrained. [ID %u]",
    609             bufferID);
    610 }
    611 
    612 void MediaFilter::onShutdown(const sp<AMessage> &msg) {
    613     mGeneration++;
    614 
    615     if (mState != UNINITIALIZED) {
    616         mFilter->reset();
    617     }
    618 
    619     int32_t keepComponentAllocated;
    620     CHECK(msg->findInt32("keepComponentAllocated", &keepComponentAllocated));
    621     if (!keepComponentAllocated || mState == UNINITIALIZED) {
    622         mState = UNINITIALIZED;
    623     } else {
    624         mState = INITIALIZED;
    625     }
    626 
    627     if (keepComponentAllocated) {
    628         mCallback->onStopCompleted();
    629     } else {
    630         mCallback->onReleaseCompleted();
    631     }
    632 }
    633 
    634 void MediaFilter::onFlush() {
    635     mGeneration++;
    636 
    637     mAvailableInputBuffers.clear();
    638     for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
    639         BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
    640         info->mStatus = BufferInfo::OWNED_BY_US;
    641     }
    642     mAvailableOutputBuffers.clear();
    643     for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
    644         BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
    645         info->mStatus = BufferInfo::OWNED_BY_US;
    646         mAvailableOutputBuffers.push_back(info);
    647     }
    648 
    649     mPortEOS[kPortIndexInput] = false;
    650     mPortEOS[kPortIndexOutput] = false;
    651     mInputEOSResult = OK;
    652 
    653     mCallback->onFlushCompleted();
    654     ALOGV("Posted kWhatFlushCompleted");
    655 
    656     // MediaCodec returns all input buffers after flush, so in
    657     // onInputBufferFilled we call postFillThisBuffer on them
    658 }
    659 
    660 void MediaFilter::onSetParameters(const sp<AMessage> &msg) {
    661     CHECK(mState != STARTED);
    662 
    663     status_t err = mFilter->setParameters(msg);
    664     if (err != (status_t)OK) {
    665         ALOGE("setParameters returned err %d", err);
    666     }
    667 }
    668 
    669 void MediaFilter::onCreateInputSurface() {
    670     CHECK(mState == CONFIGURED);
    671 
    672     mGraphicBufferListener = new GraphicBufferListener;
    673 
    674     sp<AMessage> notify = new AMessage();
    675     notify->setTarget(this);
    676     status_t err = mGraphicBufferListener->init(
    677             notify, mStride, mSliceHeight, kBufferCountActual);
    678 
    679     if (err != OK) {
    680         ALOGE("Failed to init mGraphicBufferListener: %d", err);
    681         signalError(err);
    682         return;
    683     }
    684 
    685     mCallback->onInputSurfaceCreated(
    686             nullptr, nullptr,
    687             new BufferProducerWrapper(
    688                     mGraphicBufferListener->getIGraphicBufferProducer()));
    689 }
    690 
    691 void MediaFilter::onInputFrameAvailable() {
    692     BufferItem item = mGraphicBufferListener->getBufferItem();
    693     sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item);
    694 
    695     // get pointer to graphic buffer
    696     void* bufPtr;
    697     buf->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &bufPtr);
    698 
    699     // HACK - there is no OMX_COLOR_FORMATTYPE value for RGBA, so the format
    700     // conversion is hardcoded until we add this.
    701     // TODO: check input format and convert only if necessary
    702     // copy RGBA graphic buffer into temporary ARGB input buffer
    703     BufferInfo *inputInfo = new BufferInfo;
    704     inputInfo->mData = new MediaCodecBuffer(
    705             mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4));
    706     ALOGV("Copying surface data into temp buffer.");
    707     convertRGBAToARGB(
    708             (uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(),
    709             buf->getStride(), inputInfo->mData->data());
    710     inputInfo->mBufferID = item.mSlot;
    711     inputInfo->mGeneration = mGeneration;
    712     inputInfo->mOutputFlags = 0;
    713     inputInfo->mStatus = BufferInfo::OWNED_BY_US;
    714     inputInfo->mData->meta()->setInt64("timeUs", item.mTimestamp / 1000);
    715 
    716     mAvailableInputBuffers.push_back(inputInfo);
    717 
    718     mGraphicBufferListener->releaseBuffer(item);
    719 
    720     signalProcessBuffers();
    721 }
    722 
    723 void MediaFilter::onSignalEndOfInputStream() {
    724     // if using input surface, need to send an EOS output buffer
    725     if (mGraphicBufferListener != NULL) {
    726         Vector<BufferInfo> *outputBufs = &mBuffers[kPortIndexOutput];
    727         BufferInfo* eosBuf;
    728         bool foundBuf = false;
    729         for (size_t i = 0; i < kBufferCountActual; i++) {
    730             eosBuf = &outputBufs->editItemAt(i);
    731             if (eosBuf->mStatus == BufferInfo::OWNED_BY_US) {
    732                 foundBuf = true;
    733                 break;
    734             }
    735         }
    736 
    737         if (!foundBuf) {
    738             ALOGE("onSignalEndOfInputStream failed to find an output buffer");
    739             return;
    740         }
    741 
    742         eosBuf->mOutputFlags = OMX_BUFFERFLAG_EOS;
    743         eosBuf->mGeneration = mGeneration;
    744         eosBuf->mData->setRange(0, 0);
    745         postDrainThisBuffer(eosBuf);
    746         ALOGV("Posted EOS on output buffer %u", eosBuf->mBufferID);
    747     }
    748 
    749     mPortEOS[kPortIndexOutput] = true;
    750     mCallback->onSignaledInputEOS(OK);
    751 
    752     ALOGV("Output stream saw EOS.");
    753 }
    754 
    755 }   // namespace android
    756