VTrain_BothSides/base/DvppCommonDevice/DvppCommonDevice.cpp

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;
}