void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
    IOMX::buffer_id bufferID;
    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
    BufferInfo *info = findBufferByID(kPortIndexOutput, bufferID);

    if (mState != STARTED) {
        // we're not running, so we'll just keep that buffer...
        info->mStatus = BufferInfo::OWNED_BY_US;
        return;
    }

    if (info->mGeneration != mGeneration) {
        ALOGV("Caught a stale output buffer [ID %d]", bufferID);
        // buffer is stale (taken before a flush/shutdown) - keep it
        CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
        return;
    }

    CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
    info->mStatus = BufferInfo::OWNED_BY_US;

    mAvailableOutputBuffers.push_back(info);

    processBuffers();

    ALOGV("Handled kWhatOutputBufferDrained. [ID %u]",
            bufferID);
}
status_t NuPlayerVPPProcessor::setBufferToVPP(const sp<ABuffer> &buffer, const sp<AMessage> &notifyConsumed) {
    if (!mThreadRunning)
        return VPP_OK;

    if (buffer == NULL || notifyConsumed == NULL)
        return VPP_FAIL;

    /*
     * mLastInputTimeUs >= timeBuf, means this incoming buffer is abnormal,
     * so we never send it to VPP, and mark it as notVppInput
     */
    int64_t timeBuf = getBufferTimestamp(buffer);
    if (mLastInputTimeUs >= timeBuf) {
        notifyConsumed->setInt32("notVppInput", true);
        return VPP_OK;
    }

    IOMX::buffer_id bufferID;
    CHECK(notifyConsumed->findPointer("buffer-id", &bufferID));

    ACodec::BufferInfo *info = findBufferByID(bufferID);
    CHECK(info != NULL);
    sp<GraphicBuffer> graphicBuffer = info->mGraphicBuffer;

    mInput[mInputLoadPoint].mFlags = 0;
    mInput[mInputLoadPoint].mGraphicBuffer = graphicBuffer;
    mInput[mInputLoadPoint].mTimeUs = timeBuf;
    notifyConsumed->setInt32("vppInput", true);
    mInput[mInputLoadPoint].mCodecMsg = notifyConsumed;
    mInput[mInputLoadPoint].mStatus = VPP_BUFFER_LOADED;

    mInputLoadPoint = (mInputLoadPoint + 1) % mInputBufferNum;
    mInputCount ++;
    mLastInputTimeUs = timeBuf;

    return VPP_OK;
}
void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
    IOMX::buffer_id bufferID;
    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
    BufferInfo *info = findBufferByID(kPortIndexInput, bufferID);

    if (mState != STARTED) {
        // we're not running, so we'll just keep that buffer...
        info->mStatus = BufferInfo::OWNED_BY_US;
        return;
    }

    if (info->mGeneration != mGeneration) {
        ALOGV("Caught a stale input buffer [ID %d]", bufferID);
        // buffer is stale (taken before a flush/shutdown) - repost it
        CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
        postFillThisBuffer(info);
        return;
    }

    CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
    info->mStatus = BufferInfo::OWNED_BY_US;

    sp<ABuffer> buffer;
    int32_t err = OK;
    bool eos = false;

    if (!msg->findBuffer("buffer", &buffer)) {
        // these are unfilled buffers returned by client
        CHECK(msg->findInt32("err", &err));

        if (err == OK) {
            // buffers with no errors are returned on MediaCodec.flush
            ALOGV("saw unfilled buffer (MediaCodec.flush)");
            postFillThisBuffer(info);
            return;
        } else {
            ALOGV("saw error %d instead of an input buffer", err);
            eos = true;
        }

        buffer.clear();
    }

    int32_t isCSD;
    if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
            && isCSD != 0) {
        // ignore codec-specific data buffers
        ALOGW("MediaFilter received a codec-specific data buffer");
        postFillThisBuffer(info);
        return;
    }

    int32_t tmp;
    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
        eos = true;
        err = ERROR_END_OF_STREAM;
    }

    mAvailableInputBuffers.push_back(info);
    processBuffers();

    if (eos) {
        mPortEOS[kPortIndexInput] = true;
        mInputEOSResult = err;
    }

    ALOGV("Handled kWhatInputBufferFilled. [ID %u]", bufferID);
}