/* * Copyright(C) 2020. Huawei Technologies Co.,Ltd. All rights reserved. * * 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 "DvppCommonDevice.h" #include "ErrorCode.h" #include "Log.h" APP_ERROR DvppCommonDevice::Init() { iDvppApi_ = nullptr; uint32_t ret = CreateDvppApi(iDvppApi_); if (ret != APP_ERR_OK) { LogError << "create DVPP API fail, ret=" << ret; return APP_ERR_COMM_INIT_FAIL; } return APP_ERR_OK; } APP_ERROR DvppCommonDevice::DeInit() { if (iDvppApi_ == nullptr) { LogWarn << "DVPP objet is null"; return APP_ERR_COMM_INVALID_POINTER; } uint32_t ret = DestroyDvppApi(iDvppApi_); if (ret != APP_ERR_OK) { LogError << "destroy DVPP API fail, ret=" << ret; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } APP_ERROR DvppCommonDevice::VpcResize(DvppResizeInputMsg input) { if (input.outBuf == nullptr || input.imgBuf == nullptr) { LogError << "input buffer or output buffer is null, input.imgBuf=" << (void *)input.imgBuf << ", input.outBuf=" << (void *)input.outBuf; return APP_ERR_COMM_INVALID_POINTER; } uint32_t inWidthStride = DVPP_ALIGN_UP(input.inW, VPC_WIDTH_ALIGN); uint32_t inHeightStride = DVPP_ALIGN_UP(input.inH, VPC_HEIGHT_ALIGN); SetImageConfigure(imageConfigure_, inWidthStride, inHeightStride, input.imgBuf); auto roiConfigure = std::make_shared(); roiConfigure->next = nullptr; struct VpcUserRoiInputConfigure *inputConfigure = &(roiConfigure->inputConfigure); SetCropConfigure(inputConfigure->cropArea, 0, inWidthStride - 1, 0, inHeightStride - 1); uint32_t outWidthStride = DVPP_ALIGN_UP(input.outW, VPC_WIDTH_ALIGN); uint32_t outHeightStride = DVPP_ALIGN_UP(input.outH, VPC_HEIGHT_ALIGN); struct VpcUserRoiOutputConfigure *outputConfigure = &(roiConfigure->outputConfigure); SetRoiOutputConfigure(outputConfigure, outWidthStride, outHeightStride, input.outBuf); SetCropConfigure(outputConfigure->outputArea, 0, outWidthStride - 1, 0, outHeightStride - 1); imageConfigure_.roiConfigure = roiConfigure.get(); dvppApiCtrlMsg_.in = static_cast(&imageConfigure_); dvppApiCtrlMsg_.in_size = sizeof(VpcUserImageConfigure); int ret = DvppCtl(iDvppApi_, DVPP_CTL_VPC_PROC, &dvppApiCtrlMsg_); if (ret != APP_ERR_OK) { LogError << "resize fail, ret=" << ret; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } APP_ERROR DvppCommonDevice::VpcResizeWithPadding(DvppResizeInputMsg input) { if (input.outBuf == nullptr || input.imgBuf == nullptr) { LogError << "input buffer or output buffer is null, input.imgBuf=" << (void *)input.imgBuf << ", input.outBuf=" << (void *)input.outBuf; return APP_ERR_COMM_INVALID_POINTER; } uint32_t inWidthStride = DVPP_ALIGN_UP(input.inW, VPC_HEIGHT_ALIGN); uint32_t inHeightStride = DVPP_ALIGN_UP(input.inH, VPC_HEIGHT_ALIGN); uint32_t outWidthStride = DVPP_ALIGN_UP(input.outW, VPC_WIDTH_ALIGN); uint32_t outHeightStride = DVPP_ALIGN_UP(input.outH, VPC_HEIGHT_ALIGN); SetImageConfigure(imageConfigure_, inWidthStride, inHeightStride, input.imgBuf); auto roiConfigure = std::make_shared(); roiConfigure->next = nullptr; struct VpcUserRoiInputConfigure *inputConfigure = &(roiConfigure->inputConfigure); uint32_t upOffset = 0; uint32_t downOffset = inHeightStride - 1; uint32_t leftOffset = 0; uint32_t rightOffset = inWidthStride - 1; SetCropConfigure(inputConfigure->cropArea, leftOffset, rightOffset, upOffset, downOffset); struct VpcUserRoiOutputConfigure *outputConfigure = &(roiConfigure->outputConfigure); SetRoiOutputConfigure(outputConfigure, outWidthStride, outHeightStride, input.outBuf); if ((float(inWidthStride) / float(outWidthStride)) >= (float(inHeightStride) / float(outHeightStride))) { float scale = ((float)outWidthStride) / ((float)inWidthStride); downOffset = DVPP_ALIGN_UP(uint32_t(scale * inHeightStride), VPC_OFFSET_ALIGN) - 1; rightOffset = outWidthStride - 1; } else { float scale = ((float)outHeightStride) / ((float)inHeightStride); rightOffset = DVPP_ALIGN_UP(uint32_t(scale * inWidthStride), VPC_OFFSET_ALIGN) - 1; downOffset = outHeightStride - 1; } SetCropConfigure(outputConfigure->outputArea, leftOffset, rightOffset, upOffset, downOffset); imageConfigure_.roiConfigure = roiConfigure.get(); dvppApiCtrlMsg_.in = static_cast(&imageConfigure_); dvppApiCtrlMsg_.in_size = sizeof(VpcUserImageConfigure); int ret = DvppCtl(iDvppApi_, DVPP_CTL_VPC_PROC, &dvppApiCtrlMsg_); if (ret != APP_ERR_OK) { LogError << "resize fail, ret=" << ret; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } void DvppCommonDevice::SetImageConfigure(VpcUserImageConfigure &imageConfigure, const uint32_t inWidthStride, const uint32_t inHeightStride, uint8_t *&inBuffer) { imageConfigure.bareDataAddr = inBuffer; imageConfigure.bareDataBufferSize = inWidthStride * inHeightStride * YUV_BGR_SIZE_CONVERT_3 / YUV_BGR_SIZE_CONVERT_2; imageConfigure.isCompressData = false; imageConfigure.widthStride = inWidthStride; imageConfigure.heightStride = inHeightStride; imageConfigure.inputFormat = INPUT_YUV420_SEMI_PLANNER_UV; imageConfigure.outputFormat = OUTPUT_YUV420SP_UV; imageConfigure.yuvSumEnable = false; imageConfigure.cmdListBufferAddr = nullptr; imageConfigure.cmdListBufferSize = 0; return; } void DvppCommonDevice::SetCropConfigure(VpcUserCropConfigure &cropArea, const uint32_t leftOffset, const uint32_t rightOffset, const uint32_t upOffset, const uint32_t downOffset) { cropArea.leftOffset = leftOffset; cropArea.rightOffset = rightOffset; cropArea.upOffset = upOffset; cropArea.downOffset = downOffset; return; } void DvppCommonDevice::SetRoiOutputConfigure(VpcUserRoiOutputConfigure *&outputConfigure, const uint32_t outWidthStride, const uint32_t outHeightStride, uint8_t *&outBuffer) { outputConfigure->addr = outBuffer; outputConfigure->bufferSize = outWidthStride * outHeightStride * YUV_BGR_SIZE_CONVERT_3 / YUV_BGR_SIZE_CONVERT_2; outputConfigure->widthStride = outWidthStride; outputConfigure->heightStride = outHeightStride; return; } APP_ERROR DvppCommonDevice::VpcCrop(DvppCropInputMsg input) { uint32_t inWidthStride = DVPP_ALIGN_UP(input.inW, VPC_WIDTH_ALIGN); uint32_t inHeightStride = DVPP_ALIGN_UP(input.inH, VPC_HEIGHT_ALIGN); SetImageConfigure(imageConfigure_, inWidthStride, inHeightStride, input.imgBuf); auto roiConfigure = std::make_shared(); roiConfigure->next = nullptr; struct VpcUserRoiInputConfigure *inputConfigure = &(roiConfigure->inputConfigure); uint32_t leftOffset = input.roi.left / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN; uint32_t rightOffset = input.roi.right / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN - 1; uint32_t upOffset = input.roi.up / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN; uint32_t downOffset = input.roi.down / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN - 1; SetCropConfigure(inputConfigure->cropArea, leftOffset, rightOffset, upOffset, downOffset); uint32_t outWidthStride = DVPP_ALIGN_UP(input.outW, VPC_WIDTH_ALIGN); uint32_t outHeightStride = DVPP_ALIGN_UP(input.outH, VPC_HEIGHT_ALIGN); struct VpcUserRoiOutputConfigure *outputConfigure = &(roiConfigure->outputConfigure); SetRoiOutputConfigure(outputConfigure, outWidthStride, outHeightStride, input.outBuf); SetCropConfigure(outputConfigure->outputArea, 0, outWidthStride - 1, 0, outHeightStride - 1); imageConfigure_.roiConfigure = roiConfigure.get(); dvppApiCtrlMsg_.in = static_cast(&imageConfigure_); dvppApiCtrlMsg_.in_size = sizeof(VpcUserImageConfigure); int ret = DvppCtl(iDvppApi_, DVPP_CTL_VPC_PROC, &dvppApiCtrlMsg_); if (ret != APP_ERR_OK) { LogError << "resize fail, ret=" << ret; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } APP_ERROR DvppCommonDevice::VpcMultiCrop(std::vector inputs) { LogDebug << "VpcCrop Count: " << inputs.size(); VpcUserRoiConfigure *lastRoi = nullptr; const uint32_t zero = 0; for (unsigned int i = 0; i < inputs.size(); i++) { DvppCropInputMsg input = inputs[i]; uint32_t inWidthStride = DVPP_ALIGN_UP(input.inW, VPC_WIDTH_ALIGN); uint32_t inHeightStride = DVPP_ALIGN_UP(input.inH, VPC_HEIGHT_ALIGN); SetImageConfigure(imageConfigure_, inWidthStride, inHeightStride, input.imgBuf); // std::shared_ptr roiConfigure(new VpcUserRoiConfigure); struct VpcUserRoiConfigure *roiConfigure = new VpcUserRoiConfigure(); roiConfigure->next = lastRoi; struct VpcUserRoiInputConfigure *inputConfigure = &(roiConfigure->inputConfigure); uint32_t leftOffset = input.roi.left / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN; uint32_t rightOffset = input.roi.right / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN - 1; uint32_t upOffset = input.roi.up / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN; uint32_t downOffset = input.roi.down / VPC_OFFSET_ALIGN * VPC_OFFSET_ALIGN - 1; SetCropConfigure(inputConfigure->cropArea, leftOffset, rightOffset, upOffset, downOffset); uint32_t outWidthStride = DVPP_ALIGN_UP(input.outW, VPC_WIDTH_ALIGN); uint32_t outHeightStride = DVPP_ALIGN_UP(input.outH, VPC_HEIGHT_ALIGN); struct VpcUserRoiOutputConfigure *outputConfigure = &(roiConfigure->outputConfigure); SetRoiOutputConfigure(outputConfigure, outWidthStride, outHeightStride, input.outBuf); SetCropConfigure(outputConfigure->outputArea, zero, outWidthStride - 1, zero, outHeightStride - 1); lastRoi = roiConfigure; } imageConfigure_.roiConfigure = lastRoi; dvppApiCtrlMsg_.in = static_cast(&imageConfigure_); dvppApiCtrlMsg_.in_size = sizeof(VpcUserImageConfigure); int ret = DvppCtl(iDvppApi_, DVPP_CTL_VPC_PROC, &dvppApiCtrlMsg_); while (lastRoi != nullptr) { struct VpcUserRoiConfigure *tmp = lastRoi->next; delete lastRoi; lastRoi = tmp; } if (ret != APP_ERR_OK) { LogError << "resize fail, ret=" << ret; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } APP_ERROR DvppCommonDevice::DvppJpegDecode(DvppJpegDecodeInputMsg &input) { // input setting jpegdIn_.jpegData = input.rawBuf; jpegdIn_.isYUV420Need = true; jpegdIn_.jpegDataSize = input.rawBufByteLength + DVPP_JPEG_OFFSET; jpegdIn_.isVBeforeU = false; // output setting uint32_t W_Aligned = DVPP_ALIGN_UP(input.jpegWidth, JPEG_WIDTH_ALIGN); uint32_t H_Aligned = DVPP_ALIGN_UP(input.jpegHeight, JPEG_HEIGHT_ALIGN); uint32_t outputBuffSize = W_Aligned * H_Aligned * YUV_BGR_SIZE_CONVERT_3 / YUV_BGR_SIZE_CONVERT_2; jpegdOut_.yuvData = input.decodedBuf; jpegdOut_.yuvDataSize = outputBuffSize; dvppApiCtrlMsg_.in = static_cast(&jpegdIn_); dvppApiCtrlMsg_.in_size = sizeof(JpegdIn); dvppApiCtrlMsg_.out = static_cast(&jpegdOut_); dvppApiCtrlMsg_.out_size = sizeof(JpegdOut); uint32_t ret = DvppCtl(iDvppApi_, DVPP_CTL_JPEGD_PROC, &dvppApiCtrlMsg_); if (ret != APP_ERR_OK) { LogError << "decode jpeg fail, ret=" << ret; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } uint32_t DvppCommonDevice::GetBufferSize(uint32_t w, uint32_t h) { uint32_t widthStride = DVPP_ALIGN_UP(w, VPC_WIDTH_ALIGN); uint32_t heightStride = DVPP_ALIGN_UP(h, VPC_HEIGHT_ALIGN); return widthStride * heightStride * YUV_BGR_SIZE_CONVERT_3 / YUV_BGR_SIZE_CONVERT_2; }