275 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			275 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | /*
 | ||
|  |  * 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<struct VpcUserRoiConfigure>(); | ||
|  |     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<void *>(&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<struct VpcUserRoiConfigure>(); | ||
|  |     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<void *>(&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<struct VpcUserRoiConfigure>(); | ||
|  |     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<void *>(&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<DvppCropInputMsg> 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<struct VpcUserRoiConfigure> 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<void *>(&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<void *>(&jpegdIn_); | ||
|  |     dvppApiCtrlMsg_.in_size = sizeof(JpegdIn); | ||
|  |     dvppApiCtrlMsg_.out = static_cast<void *>(&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; | ||
|  | } |