/* * Copyright 2020 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include "RTNodeVFilterZoom.h" // NOLINT #include "RTNodeCommon.h" #include "RTMediaBuffer.h" #include "RTMediaMetaKeys.h" #include "RTVideoFrame.h" #include "RTTaskNodePrivKey.h" #include #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "RTNodeVFilterZoom" #define kStubRockitZoom MKTAG('z', 'o', 'o', 'm') #define UVC_EPTZ_PAN_MAX 20.0 #define UVC_EPTZ_PAN_COUNT 40.0 #define UVC_EPTZ_TILT_MAX 20.0 #define UVC_EPTZ_TILT_COUNT 40.0 #define ALIGN2(x) (x- x % 2) #define REQUEST16B9 1 RTNodeVFilterZoom::RTNodeVFilterZoom() { mLock = new RtMutex(); RT_ASSERT(RT_NULL != mLock); mZoomValue = 10; mZoomValueNow = 10; mPanValue = 0; mPanValueNow = 0; mTiltValue = 0; mTiltValueNow = 0; mIsZoomSet = false; } RTNodeVFilterZoom::~RTNodeVFilterZoom() { rt_safe_delete(mLock); } RT_RET RTNodeVFilterZoom::open(RTTaskNodeContext *context) { RtMetaData* inputMeta = context->options(); RT_RET err = RT_OK; RT_ASSERT(inputMeta->findInt32(OPT_VIDEO_WIDTH, &mSrcWidth)); RT_ASSERT(inputMeta->findInt32(OPT_VIDEO_HEIGHT, &mSrcHeight)); RT_ASSERT(inputMeta->findInt32(OPT_EPTZ_CLIP_WIDTH, &mDstWidth)); RT_ASSERT(inputMeta->findInt32(OPT_EPTZ_CLIP_HEIGHT, &mDstHeight)); mEptzOffsetX = 0; mEptzOffsetY = 0; mEptzWidth = mSrcWidth; mEptzHeight = mSrcHeight; return RT_OK; } RT_RET RTNodeVFilterZoom::process(RTTaskNodeContext *context) { RT_RET err = RT_OK; RTVideoFrame *srcVFrame = RT_NULL; RTVideoFrame *dstVFrame = RT_NULL; RTCropInfo *cropInfo = RT_NULL; if (!context->inputIsEmpty()) { srcVFrame = reinterpret_vframe(context->dequeInputBuffer()); RT_ASSERT(srcVFrame != RT_NULL); if (srcVFrame->getOpRect().w != 0 && srcVFrame->getOpRect().h != 0) { mEptzOffsetX = srcVFrame->getOpRect().x; mEptzOffsetY = srcVFrame->getOpRect().y; mEptzWidth = srcVFrame->getOpRect().w; mEptzHeight = srcVFrame->getOpRect().h; } mSrcWidth = srcVFrame->getVirWidth(); mSrcHeight = srcVFrame->getVirHeight(); //RT_LOGE("zoom get format[%d]", format); RTZoomCalculate(); RTRect srcRect; RTCropInfo dstCropInfo; srcRect.x = mResult[0]; srcRect.y = mResult[1]; srcRect.w = mResult[2]; srcRect.h = mResult[3]; dstCropInfo.region.x = 0; dstCropInfo.region.y = 0; dstCropInfo.region.w = mDstWidth; dstCropInfo.region.h = mDstHeight; dstCropInfo.virWidth = mDstWidth; dstCropInfo.virHeight = mDstHeight; dstVFrame = clone_vframe(srcVFrame); dstVFrame->setOpRect(srcRect); dstVFrame->setVirWidth(mSrcWidth); dstVFrame->setVirHeight(mSrcHeight); dstVFrame->getMetaData()->setStructData(KEY_COMM_DST_CROP, &dstCropInfo, sizeof(RTCropInfo)); dstVFrame->setSeq(srcVFrame->getSeq()); dstVFrame->setPts(srcVFrame->getPts()); dstVFrame->setPixelFormat(srcVFrame->getPixelFormat()); context->queueOutputBuffer(dstVFrame); srcVFrame->release(); srcVFrame = RT_NULL; } return err; } void RTNodeVFilterZoom::RTZoomCalculate(){ RT_LOGV("RTZoomCalculate enter , mZoomValue %.2f mZoomValueNow %.2f mPanValue %d mPanValueNow %d mTiltValue %d mTiltValueNow %d", mZoomValue, mZoomValueNow, mPanValue, mPanValueNow, mTiltValue, mTiltValueNow); if (mZoomValue > 10 || mZoomValueNow > 10) { mIsZoomSet = true; if (mZoomValueNow > mZoomValue) { if (mZoomValueNow - 10 > mZoomValue) mZoomValueNow -= 8; else if (mZoomValueNow - 5 > mZoomValue) mZoomValueNow -= 4; else mZoomValueNow -= 1; } else if (mZoomValueNow < mZoomValue) { if (mZoomValueNow + 10 < mZoomValue) mZoomValueNow += 8; else if (mZoomValueNow + 5 < mZoomValue) mZoomValueNow += 4; else mZoomValueNow += 1; } }else { mIsZoomSet = false; } int zoomIndex = (mZoomValueNow - 10); float ratio = (float)(mEptzWidth) / (float)(mSrcWidth); float zoomPerCrease = mSrcWidth * 1.0 / 16.0 / 80.0 * ratio; RT_LOGV("zoomIndex %d , ratio %.2f zoomPerCrease %.2f", zoomIndex, ratio, zoomPerCrease); RT_LOGV("mEPTZ Orignal xywh[%d %d %d %d] srcwh[%d %d] dstwh[%d %d]", mEptzOffsetX, mEptzOffsetY, mEptzWidth, mEptzHeight, mSrcWidth, mSrcHeight, mDstWidth, mDstHeight); float mEptzWidthF, mEptzHeightF, mEptzOffsetXF, mEptzOffsetYF; mEptzWidthF = (float)(mEptzWidth) - zoomIndex * zoomPerCrease * 16; mEptzHeightF = (float)(mEptzHeight) - zoomIndex * zoomPerCrease * 9; // mEptzOffsetXF = (float)(mEptzOffsetX) + (zoomIndex * zoomPerCrease * 16) / 2; // mEptzOffsetYF = (float)(mEptzOffsetY) + (zoomIndex * zoomPerCrease * 9) / 2; RT_LOGV("mEPTZ After ZOOM xywh[%.3f %.3f %.3f %.3f]", mEptzOffsetXF, mEptzOffsetYF, mEptzWidthF, mEptzHeightF); if (mIsZoomSet == false) { if (mPanValueNow > mPanValue) { if (mPanValueNow - 8 > mPanValue) mPanValueNow -= 6; else if (mPanValueNow - 5 > mPanValue) mPanValueNow -= 3; else mPanValueNow -= 1; }else if (mPanValueNow < mPanValue) { if (mPanValueNow + 8 < mPanValue) mPanValueNow += 6; else if (mPanValueNow + 5 < mPanValue) mPanValueNow += 3; else mPanValueNow += 1; } if (mTiltValueNow > mTiltValue) { if (mTiltValueNow - 8 > mTiltValue) mTiltValueNow -= 6; else if (mTiltValueNow - 5 > mTiltValue) mTiltValueNow -= 3; else mTiltValueNow -= 1; }else if (mTiltValueNow < mTiltValue) { if (mTiltValueNow + 8 < mTiltValue) mTiltValueNow += 6; else if (mTiltValueNow + 5 < mTiltValue) mTiltValueNow += 3; else mTiltValueNow += 1; } }else { mPanValueNow = mPanValue; mTiltValueNow = mTiltValue; } float pan_value = (zoomIndex * zoomPerCrease * 16) * (mPanValueNow + UVC_EPTZ_PAN_MAX) / UVC_EPTZ_PAN_COUNT; float tilt_value = (zoomIndex * zoomPerCrease * 9) * (mTiltValueNow + UVC_EPTZ_TILT_MAX) / UVC_EPTZ_TILT_COUNT; mEptzOffsetXF = (float)(mEptzOffsetX) + pan_value; mEptzOffsetYF = (float)(mEptzOffsetY) + tilt_value; if(REQUEST16B9 && ((mDstWidth == 1024 && mDstHeight == 768) || (mDstWidth == 640 && mDstHeight == 480) || (mDstWidth == 320 && mDstHeight == 240))){ float modify_x = mEptzWidthF - (float)(mEptzHeightF) * 4 / 3; mEptzWidthF = mEptzWidthF - modify_x; mEptzOffsetXF = mEptzOffsetXF + modify_x / 2; RT_LOGV("640x480 2 16:9 modify_x %.3f mEptzWidth %.3f mEptzOffsetX %.3f", modify_x, mEptzWidthF, mEptzOffsetXF); } mResult[0] = ALIGN2((int)mEptzOffsetXF); mResult[1] = ALIGN2((int)mEptzOffsetYF); mResult[2] = ALIGN2((int)mEptzWidthF); mResult[3] = ALIGN2((int)mEptzHeightF); RT_LOGV("mEPTZ ZOOM pt[%.3f %.3f] 2Align xywh[%d %d %d %d]", pan_value, tilt_value, mResult[0], mResult[1], mResult[2], mResult[3]); } RT_RET RTNodeVFilterZoom::invokeInternal(RtMetaData *meta) { const char *command; if (RT_NULL == meta) { return RT_ERR_NULL_PTR; } RtMutex::RtAutolock autoLock(mLock); meta->findCString(kKeyPipeInvokeCmd, &command); RT_LOGD("invoke(%s) internally.", command); RTSTRING_SWITCH(command) { RTSTRING_CASE("set_zoom"): RT_ASSERT(meta->findFloat("value", &mZoomValue)); mZoomValue = mZoomValue * 10; break; RTSTRING_CASE("set_pan"): RT_ASSERT(meta->findInt32("value", &mPanValue)); mPanValue = mPanValue * 2; break; RTSTRING_CASE("set_tilt"): RT_ASSERT(meta->findInt32("value", &mTiltValue)); mTiltValue = mTiltValue * 2; break; RTSTRING_CASE("reset_position"): RT_LOGD("zoom reset position [0 0 %d %d]", mSrcWidth, mSrcHeight); mEptzOffsetX = 0; mEptzOffsetY = 0; mEptzWidth = mSrcWidth; mEptzHeight = mSrcHeight; break; default: RT_LOGD("unsupported command=%d", command); break; } RT_LOGD("invokeInternal, mZoomValue %.2f mPanValue %d mTiltValue %d mDstWH[%d %d]", mZoomValue, mPanValue, mTiltValue, mDstWidth, mDstHeight); return RT_OK; } RT_RET RTNodeVFilterZoom::close(RTTaskNodeContext *context) { RT_RET err = RT_OK; return err; } static RTTaskNode* createZoomFilter() { return new RTNodeVFilterZoom(); } /***************************************** * register node stub to RTTaskNodeFactory *****************************************/ RTNodeStub node_stub_filter_zoom_demo { .mUid = kStubRockitZoom, .mName = "rkzoom", .mVersion = "v1.0", .mCreateObj = createZoomFilter, .mCapsSrc = { "video/x-raw", RT_PAD_SRC, RT_MB_TYPE_VFRAME, {RT_NULL, RT_NULL}, }, .mCapsSink = { "video/x-raw", RT_PAD_SINK, RT_MB_TYPE_VFRAME, {RT_NULL, RT_NULL} }, }; RT_NODE_FACTORY_REGISTER_STUB(node_stub_filter_zoom_demo);