From e2d34959250b712c3c73afe446d48860ccb8526e Mon Sep 17 00:00:00 2001 From: Zhenglong Li Date: Fri, 5 Feb 2021 16:46:24 +0800 Subject: [PATCH] Dvpp refactor and 6 Dvpp operators --- .../ccsrc/minddata/dataset/api/execute.cc | 286 +++++- .../ccsrc/minddata/dataset/api/vision.cc | 267 +++++ .../minddata/dataset/core/CMakeLists.txt | 23 +- .../ccsrc/minddata/dataset/core/de_tensor.cc | 36 +- .../ccsrc/minddata/dataset/core/de_tensor.h | 8 +- .../minddata/dataset/core/device_tensor.cc | 77 ++ .../minddata/dataset/core/device_tensor.h | 65 ++ .../minddata/dataset/core/global_context.cc | 4 +- .../minddata/dataset/core/global_context.h | 27 +- .../ccsrc/minddata/dataset/core/tensor.h | 16 + .../ccsrc/minddata/dataset/include/execute.h | 19 +- .../ccsrc/minddata/dataset/include/vision.h | 17 - .../minddata/dataset/include/vision_ascend.h | 219 ++++ .../dataset/kernels/image/dvpp/CMakeLists.txt | 7 +- .../kernels/image/dvpp/dvpp_crop_jpeg_op.cc | 145 +++ .../kernels/image/dvpp/dvpp_crop_jpeg_op.h | 62 ++ .../kernels/image/dvpp/dvpp_decode_jpeg_op.cc | 139 +++ .../kernels/image/dvpp/dvpp_decode_jpeg_op.h | 59 ++ .../kernels/image/dvpp/dvpp_decode_png_op.cc | 138 +++ .../kernels/image/dvpp/dvpp_decode_png_op.h | 58 ++ .../dvpp/dvpp_decode_resize_crop_jpeg_op.cc | 70 +- .../dvpp/dvpp_decode_resize_crop_jpeg_op.h | 22 +- .../image/dvpp/dvpp_decode_resize_jpeg_op.cc | 134 +++ .../image/dvpp/dvpp_decode_resize_jpeg_op.h | 62 ++ .../kernels/image/dvpp/dvpp_resize_jpeg_op.cc | 147 +++ .../kernels/image/dvpp/dvpp_resize_jpeg_op.h | 63 ++ .../kernels/image/dvpp/utils/AclProcess.cc | 255 ----- .../kernels/image/dvpp/utils/AclProcess.h | 80 -- .../kernels/image/dvpp/utils/CMakeLists.txt | 2 +- .../kernels/image/dvpp/utils/CommonDataType.h | 14 +- .../kernels/image/dvpp/utils/DvppCommon.cc | 405 +++++++- .../kernels/image/dvpp/utils/DvppCommon.h | 35 +- .../kernels/image/dvpp/utils/ErrorCode.cpp | 5 +- .../kernels/image/dvpp/utils/ErrorCode.h | 8 +- .../kernels/image/dvpp/utils/MDAclProcess.cc | 966 ++++++++++++++++++ .../kernels/image/dvpp/utils/MDAclProcess.h | 139 +++ .../image/dvpp/utils/ResourceManager.cc | 9 +- .../image/dvpp/utils/ResourceManager.h | 14 +- .../dataset/kernels/image/image_utils.cc | 8 +- .../dataset/kernels/image/image_utils.h | 2 + .../dataset/kernels/ir/vision/vision_ir.cc | 99 -- .../dataset/kernels/ir/vision/vision_ir.h | 19 - .../minddata/dataset/kernels/tensor_op.cc | 13 + .../minddata/dataset/kernels/tensor_op.h | 18 + tests/st/cpp/CMakeLists.txt | 3 + tests/st/cpp/dataset/test_de.cc | 64 +- tests/ut/cpp/CMakeLists.txt | 7 + tests/ut/cpp/dataset/CMakeLists.txt | 6 + tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc | 40 + 49 files changed, 3743 insertions(+), 638 deletions(-) create mode 100644 mindspore/ccsrc/minddata/dataset/core/device_tensor.cc create mode 100644 mindspore/ccsrc/minddata/dataset/core/device_tensor.h create mode 100644 mindspore/ccsrc/minddata/dataset/include/vision_ascend.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h delete mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.cc delete mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h create mode 100644 tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc diff --git a/mindspore/ccsrc/minddata/dataset/api/execute.cc b/mindspore/ccsrc/minddata/dataset/api/execute.cc index fbdd553132..c69cf2d5dc 100644 --- a/mindspore/ccsrc/minddata/dataset/api/execute.cc +++ b/mindspore/ccsrc/minddata/dataset/api/execute.cc @@ -16,6 +16,7 @@ #include "minddata/dataset/include/execute.h" #include "minddata/dataset/core/de_tensor.h" +#include "minddata/dataset/core/device_tensor.h" #include "minddata/dataset/core/tensor_row.h" #include "minddata/dataset/include/tensor.h" #include "minddata/dataset/include/type_id.h" @@ -25,53 +26,194 @@ #else #include "mindspore/lite/src/common/log_adapter.h" #endif +#ifdef ENABLE_ACL +#include "acl/acl.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h" +#endif namespace mindspore { namespace dataset { +#ifdef ENABLE_ACL +class AscendResource { + public: + AscendResource(); + ~AscendResource() = default; + + Status InitChipResource(); + + Status FinalizeChipResource(); + + Status Sink(const mindspore::MSTensor &host_input, std::shared_ptr *device_input); + + Status Pop(std::shared_ptr device_output, std::shared_ptr *host_output); + + Status DeviceDataRelease(); + + std::shared_ptr processor_; + std::shared_ptr ascend_resource_; +}; + +AscendResource::AscendResource() { InitChipResource(); } + +Status AscendResource::InitChipResource() { + ResourceInfo resource; + resource.aclConfigPath = ""; + resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); + ascend_resource_ = ResourceManager::GetInstance(); + APP_ERROR ret = ascend_resource_->InitResource(resource); + if (ret != APP_ERR_OK) { + ascend_resource_->Release(); + std::string err_msg = "Error in Init D-chip:" + std::to_string(ret); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + int device_id = *(resource.deviceIds.begin()); + aclrtContext context = ascend_resource_->GetContext(device_id); + processor_ = std::make_shared(context, false); + ret = processor_->InitResource(); + if (ret != APP_ERR_OK) { + ascend_resource_->Release(); + std::string err_msg = "Error in Init resource:" + std::to_string(ret); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + MS_LOG(INFO) << "Ascend resource all initialized!"; + return Status::OK(); +} + +Status AscendResource::FinalizeChipResource() { + processor_->Release(); + return Status::OK(); +} + +Status AscendResource::Sink(const mindspore::MSTensor &host_input, std::shared_ptr *device_input) { + std::shared_ptr de_input; + Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(host_input.Shape()), + MSTypeToDEType(static_cast(host_input.DataType())), + (const uchar *)(host_input.Data().get()), &de_input); + RETURN_IF_NOT_OK(rc); + APP_ERROR ret = processor_->H2D_Sink(de_input, *device_input); + if (ret != APP_ERR_OK) { + ascend_resource_->Release(); + std::string err_msg = "Error in data sink process:" + std::to_string(ret); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + MS_LOG(INFO) << "Process data sink successfully"; + return Status::OK(); +} -Execute::Execute(std::shared_ptr op) { ops_.emplace_back(std::move(op)); } +Status AscendResource::Pop(std::shared_ptr device_output, std::shared_ptr *host_output) { + APP_ERROR ret = processor_->D2H_Pop(device_output, *host_output); + if (ret != APP_ERR_OK) { + ascend_resource_->Release(); + std::string err_msg = "Error in data pop processing:" + std::to_string(ret); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + return Status::OK(); +} + +Status AscendResource::DeviceDataRelease() { + APP_ERROR ret = processor_->device_memory_release(); + if (ret != APP_ERR_OK) { + ascend_resource_->Release(); + std::string err_msg = "Error in device data release:" + std::to_string(ret); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + return Status::OK(); +} +#endif + +Execute::Execute(std::shared_ptr op, std::string deviceType) { + ops_.emplace_back(std::move(op)); + device_type_ = deviceType; + MS_LOG(INFO) << "Running Device: " << device_type_; +#ifdef ENABLE_ACL + if (device_type_ == "Ascend310") { + D_resource_ = std::make_shared(); + } +#endif +} + +Execute::Execute(std::vector> ops, std::string deviceType) + : ops_(std::move(ops)), device_type_(deviceType) { + MS_LOG(INFO) << "Running Device: " << device_type_; +#ifdef ENABLE_ACL + if (device_type_ == "Ascend310") { + D_resource_ = std::make_shared(); + } +#endif +} -Execute::Execute(std::vector> ops) : ops_(std::move(ops)) {} +Execute::~Execute() { +#ifdef ENABLE_ACL + if (device_type_ == "Ascend310") { + D_resource_->FinalizeChipResource(); + } +#endif +} Status Execute::operator()(const mindspore::MSTensor &input, mindspore::MSTensor *output) { // Validate input tensor CHECK_FAIL_RETURN_UNEXPECTED(input.DataSize() > 0, "Input Tensor has no data"); CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided"); - + CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'"); // Validate and build runtime ops - std::vector> transforms; + std::vector> transforms; // record the transformations for (int32_t i = 0; i < ops_.size(); i++) { CHECK_FAIL_RETURN_UNEXPECTED(ops_[i] != nullptr, "Input TensorOperation[" + std::to_string(i) + "] is null"); RETURN_IF_NOT_OK(ops_[i]->ValidateParams()); transforms.emplace_back(ops_[i]->Build()); } + if (device_type_ == "CPU") { + // Convert mindspore::Tensor to dataset::Tensor + std::shared_ptr de_tensor; + Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()), + MSTypeToDEType(static_cast(input.DataType())), + (const uchar *)(input.Data().get()), input.DataSize(), &de_tensor); + if (rc.IsError()) { + MS_LOG(ERROR) << rc; + return rc; + } - // Convert mindspore::Tensor to dataset::Tensor - std::shared_ptr de_tensor; - Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()), - MSTypeToDEType(static_cast(input.DataType())), - (const uchar *)(input.Data().get()), input.DataSize(), &de_tensor); - if (rc.IsError()) { - MS_LOG(ERROR) << rc; - RETURN_IF_NOT_OK(rc); - } + // Apply transforms on tensor + for (auto &t : transforms) { + std::shared_ptr de_output; + Status rc_ = t->Compute(de_tensor, &de_output); + if (rc_.IsError()) { + MS_LOG(ERROR) << rc_; + return rc_; + } - // Apply transforms on tensor - for (auto &t : transforms) { - std::shared_ptr de_output; - Status rc_ = t->Compute(de_tensor, &de_output); - if (rc_.IsError()) { - MS_LOG(ERROR) << rc_; - RETURN_IF_NOT_OK(rc_); + // For next transform + de_tensor = std::move(de_output); } - // For next transform - de_tensor = std::move(de_output); - } + // Convert dataset::Tensor to mindspore::Tensor + CHECK_FAIL_RETURN_UNEXPECTED(de_tensor->HasData(), "Apply transform failed, output tensor has no data"); + *output = mindspore::MSTensor(std::make_shared(de_tensor)); + } else { // Ascend310 case, where we must set Ascend resource on each operators +#ifdef ENABLE_ACL + std::shared_ptr device_input; + RETURN_IF_NOT_OK(D_resource_->Sink(input, &device_input)); + for (auto &t : transforms) { + std::shared_ptr device_output; + RETURN_IF_NOT_OK(t->SetAscendResource(D_resource_->processor_)); + RETURN_IF_NOT_OK(t->Compute(device_input, &device_output)); - // Convert dataset::Tensor to mindspore::Tensor - CHECK_FAIL_RETURN_UNEXPECTED(de_tensor->HasData(), "Apply transform failed, output tensor has no data"); - *output = mindspore::MSTensor(std::make_shared(de_tensor)); + // For next transform + device_input = std::move(device_output); + } + CHECK_FAIL_RETURN_UNEXPECTED(device_input->HasDeviceData(), "Apply transform failed, output tensor has no data"); + *output = mindspore::MSTensor(std::make_shared(device_input, true)); +#endif + } return Status::OK(); } @@ -82,6 +224,7 @@ Status Execute::operator()(const std::vector &input_tensor_list, std:: CHECK_FAIL_RETURN_UNEXPECTED(tensor.DataSize() > 0, "Input Tensor has no data"); } CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided"); + CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'"); // Validate and build runtime ops std::vector> transforms; @@ -90,40 +233,81 @@ Status Execute::operator()(const std::vector &input_tensor_list, std:: RETURN_IF_NOT_OK(ops_[i]->ValidateParams()); transforms.emplace_back(ops_[i]->Build()); } + if (device_type_ == "CPU") { // Case CPU + TensorRow de_tensor_list; + for (auto &tensor : input_tensor_list) { + std::shared_ptr de_tensor; + Status rc = dataset::Tensor::CreateFromMemory( + dataset::TensorShape(tensor.Shape()), MSTypeToDEType(static_cast(tensor.DataType())), + (const uchar *)(tensor.Data().get()), tensor.DataSize(), &de_tensor); + if (rc.IsError()) { + MS_LOG(ERROR) << rc; + RETURN_IF_NOT_OK(rc); + } + de_tensor_list.emplace_back(std::move(de_tensor)); + } + // Apply transforms on tensor + for (auto &t : transforms) { + TensorRow de_output_list; + RETURN_IF_NOT_OK(t->Compute(de_tensor_list, &de_output_list)); + // For next transform + de_tensor_list = std::move(de_output_list); + } - TensorRow de_tensor_list; - for (auto &tensor : input_tensor_list) { - std::shared_ptr de_tensor; - Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(tensor.Shape()), - MSTypeToDEType(static_cast(tensor.DataType())), - (const uchar *)(tensor.Data().get()), tensor.DataSize(), &de_tensor); - if (rc.IsError()) { - MS_LOG(ERROR) << rc; - RETURN_IF_NOT_OK(rc); + for (auto &tensor : de_tensor_list) { + CHECK_FAIL_RETURN_UNEXPECTED(tensor->HasData(), "Apply transform failed, output tensor has no data"); + auto ms_tensor = mindspore::MSTensor(std::make_shared(tensor)); + output_tensor_list->emplace_back(ms_tensor); } - de_tensor_list.emplace_back(std::move(de_tensor)); - } + CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor is not valid"); + } else { // Case Ascend310 +#ifdef ENABLE_ACL + for (auto &input_tensor : input_tensor_list) { + std::shared_ptr device_input; + RETURN_IF_NOT_OK(D_resource_->Sink(input_tensor, &device_input)); + for (auto &t : transforms) { + std::shared_ptr device_output; + RETURN_IF_NOT_OK(t->SetAscendResource(D_resource_->processor_)); + RETURN_IF_NOT_OK(t->Compute(device_input, &device_output)); - // Apply transforms on tensor - for (auto &t : transforms) { - TensorRow de_output_list; - Status rc = t->Compute(de_tensor_list, &de_output_list); - if (rc.IsError()) { - MS_LOG(ERROR) << rc; - RETURN_IF_NOT_OK(rc); + // For next transform + device_input = std::move(device_output); + } + CHECK_FAIL_RETURN_UNEXPECTED(device_input->HasDeviceData(), "Apply transform failed, output tensor has no data"); + // Due to the limitation of Ascend310 memory, we have to pop every data onto host memory + // So the speed of this method is slower than solo mode + std::shared_ptr host_output; + RETURN_IF_NOT_OK(D_resource_->Pop(device_input, &host_output)); + auto ms_tensor = mindspore::MSTensor(std::make_shared(host_output)); + output_tensor_list->emplace_back(ms_tensor); + RETURN_IF_NOT_OK(D_resource_->DeviceDataRelease()); } - // For next transform - de_tensor_list = std::move(de_output_list); + CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor vector is empty"); +#endif } + return Status::OK(); +} - for (auto &tensor : de_tensor_list) { - CHECK_FAIL_RETURN_UNEXPECTED(tensor->HasData(), "Apply transform failed, output tensor has no data"); - auto ms_tensor = mindspore::MSTensor(std::make_shared(tensor)); - output_tensor_list->emplace_back(ms_tensor); +Status Execute::validate_device_() { + if (device_type_ != "CPU" && device_type_ != "Ascend310") { + std::string err_msg = device_type_ + " is not supported. (Option: CPU or Ascend310)"; + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); } - CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor is not valid"); return Status::OK(); } +#ifdef ENABLE_ACL +Status Execute::DeviceMemoryRelease() { + Status rc = D_resource_->DeviceDataRelease(); + if (rc.IsError()) { + D_resource_->ascend_resource_->Release(); + std::string err_msg = "Error in device data release"; + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + return Status::OK(); +} +#endif } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/api/vision.cc b/mindspore/ccsrc/minddata/dataset/api/vision.cc index e2e813e8f7..c78c98f59c 100644 --- a/mindspore/ccsrc/minddata/dataset/api/vision.cc +++ b/mindspore/ccsrc/minddata/dataset/api/vision.cc @@ -37,7 +37,13 @@ #endif #include "minddata/dataset/kernels/image/decode_op.h" #ifdef ENABLE_ACL +#include "minddata/dataset/include/vision_ascend.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h" #include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h" #endif #ifndef ENABLE_ANDROID #include "minddata/dataset/kernels/image/equalize_op.h" @@ -143,6 +149,20 @@ std::shared_ptr Decode(bool rgb) { } #ifdef ENABLE_ACL +// Function to create DvppResizeOperation. +std::shared_ptr DvppCropJpeg(std::vector crop) { + auto op = std::make_shared(crop); + // Input validation + return op->ValidateParams() ? op : nullptr; +} + +// Function to create DvppDecodeResizeOperation. +std::shared_ptr DvppDecodeResizeJpeg(std::vector resize) { + auto op = std::make_shared(resize); + // Input validation + return op->ValidateParams() ? op : nullptr; +} + // Function to create DvppDecodeResizeCropOperation. std::shared_ptr DvppDecodeResizeCropJpeg(std::vector crop, std::vector resize) { @@ -150,6 +170,27 @@ std::shared_ptr DvppDecodeResizeCropJpeg(std::vec // Input validation return op->ValidateParams() ? op : nullptr; } + +// Function to create DvppDecodeJpegOperation. +std::shared_ptr DvppDecodeJpeg() { + auto op = std::make_shared(); + // Input validation + return op->ValidateParams() ? op : nullptr; +} + +// Function to create DvppDecodePngOperation. +std::shared_ptr DvppDecodePng() { + auto op = std::make_shared(); + // Input validation + return op->ValidateParams() ? op : nullptr; +} + +// Function to create DvppResizeOperation. +std::shared_ptr DvppResizeJpeg(std::vector resize) { + auto op = std::make_shared(resize); + // Input validation + return op->ValidateParams() ? op : nullptr; +} #endif // Function to create EqualizeOperation. @@ -445,6 +486,232 @@ std::shared_ptr UniformAugment(std::vector &crop) : crop_(crop) {} + +Status DvppCropJpegOperation::ValidateParams() { + // size + if (crop_.empty() || crop_.size() > 2) { + std::string err_msg = + "DvppCropJpeg: Crop resolution must be a vector of one or two elements, got: " + std::to_string(crop_.size()); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) { + std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got crop Parameters: "; + if (crop_.size() == 2) { + MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]"; + } else { + MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]"; + } + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + return Status::OK(); +} + +std::shared_ptr DvppCropJpegOperation::Build() { + // If size is a single value, the smaller edge of the image will be + // resized to this value with the same image aspect ratio. + uint32_t cropHeight, cropWidth; + // User specified the width value. + if (crop_.size() == 1) { + cropHeight = crop_[0]; + cropWidth = crop_[0]; + } else { + cropHeight = crop_[0]; + cropWidth = crop_[1]; + } + std::shared_ptr tensor_op = std::make_shared(cropHeight, cropWidth); + return tensor_op; +} + +// DvppDecodeResizeOperation +DvppDecodeResizeOperation::DvppDecodeResizeOperation(const std::vector &resize) : resize_(resize) {} + +Status DvppDecodeResizeOperation::ValidateParams() { + // size + if (resize_.empty() || resize_.size() > 2) { + std::string err_msg = "DvppDecodeResizeJpeg: resize resolution must be a vector of one or two elements, got: " + + std::to_string(resize_.size()); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) { + std::string err_msg = + "Dvpp module supports resize image with resolution in range [32, 2048], got resize Parameters: "; + if (resize_.size() == 2) { + MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]"; + } else { + MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]"; + } + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + return Status::OK(); +} + +std::shared_ptr DvppDecodeResizeOperation::Build() { + // If size is a single value, the smaller edge of the image will be + // resized to this value with the same image aspect ratio. + uint32_t resizeHeight, resizeWidth; + // User specified the width value. + if (resize_.size() == 1) { + resizeHeight = resize_[0]; + resizeWidth = 0; + } else { + resizeHeight = resize_[0]; + resizeWidth = resize_[1]; + } + std::shared_ptr tensor_op = + std::make_shared(resizeHeight, resizeWidth); + return tensor_op; +} + +// DvppDecodeResizeCropOperation +DvppDecodeResizeCropOperation::DvppDecodeResizeCropOperation(const std::vector &crop, + const std::vector &resize) + : crop_(crop), resize_(resize) {} + +Status DvppDecodeResizeCropOperation::ValidateParams() { + // size + if (crop_.empty() || crop_.size() > 2) { + std::string err_msg = "DvppDecodeResizeCropJpeg: crop resolution must be a vector of one or two elements, got: " + + std::to_string(crop_.size()); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (resize_.empty() || resize_.size() > 2) { + std::string err_msg = "DvppDecodeResizeCropJpeg: resize resolution must be a vector of one or two elements, got: " + + std::to_string(resize_.size()); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) { + std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got Crop Parameters: "; + if (crop_.size() == 2) { + MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]"; + } else { + MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]"; + } + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) { + std::string err_msg = + "Dvpp module supports resize image with resolution in range [32, 2048], got Crop Parameters: "; + if (resize_.size() == 2) { + MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]"; + } else { + MS_LOG(ERROR) << err_msg << "[" << resize_[0] << "]"; + } + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (crop_.size() < resize_.size()) { + if (crop_[0] > MIN(resize_[0], resize_[1])) { + std::string err_msg = + "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= " + "y[0], and x[1] <= y[1], please verify your input parameters."; + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + } + if (crop_.size() > resize_.size()) { + if (MAX(crop_[0], crop_[1]) > resize_[0]) { + std::string err_msg = + "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= " + "y[0], and x[1] <= y[1], please verify your input parameters."; + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + } + if (crop_.size() == resize_.size()) { + for (int32_t i = 0; i < crop_.size(); ++i) { + if (crop_[i] > resize_[i]) { + std::string err_msg = + "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= " + "y[0], and x[1] <= y[1], please verify your input parameters."; + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + } + } + return Status::OK(); +} + +std::shared_ptr DvppDecodeResizeCropOperation::Build() { + // If size is a single value, the smaller edge of the image will be + // resized to this value with the same image aspect ratio. + uint32_t cropHeight, cropWidth, resizeHeight, resizeWidth; + if (crop_.size() == 1) { + cropHeight = crop_[0]; + cropWidth = crop_[0]; + } else { + cropHeight = crop_[0]; + cropWidth = crop_[1]; + } + // User specified the width value. + if (resize_.size() == 1) { + resizeHeight = resize_[0]; + resizeWidth = 0; + } else { + resizeHeight = resize_[0]; + resizeWidth = resize_[1]; + } + std::shared_ptr tensor_op = + std::make_shared(cropHeight, cropWidth, resizeHeight, resizeWidth); + return tensor_op; +} + +// DvppDecodeJPEG +Status DvppDecodeJpegOperation::ValidateParams() { return Status::OK(); } + +std::shared_ptr DvppDecodeJpegOperation::Build() { return std::make_shared(); } + +// DvppDecodePNG +Status DvppDecodePngOperation::ValidateParams() { return Status::OK(); } + +std::shared_ptr DvppDecodePngOperation::Build() { return std::make_shared(); } + +// DvppResizeOperation +DvppResizeJpegOperation::DvppResizeJpegOperation(const std::vector &resize) : resize_(resize) {} + +Status DvppResizeJpegOperation::ValidateParams() { + // size + if (resize_.empty() || resize_.size() > 2) { + std::string err_msg = "DvppResizeJpeg: resize resolution must be a vector of one or two elements, got: " + + std::to_string(resize_.size()); + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) { + std::string err_msg = + "Dvpp module supports resize image with resolution in range [32, 2048], got resize Parameters: "; + if (resize_.size() == 2) { + MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]"; + } else { + MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]"; + } + RETURN_STATUS_SYNTAX_ERROR(err_msg); + } + return Status::OK(); +} + +std::shared_ptr DvppResizeJpegOperation::Build() { + // If size is a single value, the smaller edge of the image will be + // resized to this value with the same image aspect ratio. + uint32_t resizeHeight, resizeWidth; + // User specified the width value. + if (resize_.size() == 1) { + resizeHeight = resize_[0]; + resizeWidth = 0; + } else { + resizeHeight = resize_[0]; + resizeWidth = resize_[1]; + } + std::shared_ptr tensor_op = std::make_shared(resizeHeight, resizeWidth); + return tensor_op; +} +#endif + } // namespace vision } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/core/CMakeLists.txt b/mindspore/ccsrc/minddata/dataset/core/CMakeLists.txt index 9a204f6deb..c03dcf3263 100644 --- a/mindspore/ccsrc/minddata/dataset/core/CMakeLists.txt +++ b/mindspore/ccsrc/minddata/dataset/core/CMakeLists.txt @@ -1,17 +1,18 @@ file(GLOB_RECURSE _CURRENT_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc") set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD) set(DATASET_CORE_SRC_FILES - client.cc - config_manager.cc - cv_tensor.cc - data_type.cc - de_tensor.cc - global_context.cc - tensor.cc - tensor_helpers.cc - tensor_row.cc - tensor_shape.cc -) + client.cc + config_manager.cc + cv_tensor.cc + data_type.cc + device_tensor.cc + de_tensor.cc + global_context.cc + tensor.cc + tensor_helpers.cc + tensor_row.cc + tensor_shape.cc + ) ms_protobuf_generate(EXAMPLE_SRCS EXAMPLE_HDRS example.proto) ms_protobuf_generate(FEATURE_SRCS FEATURE_HDRS feature.proto) diff --git a/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc b/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc index 041533fd91..68df7109bd 100644 --- a/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc +++ b/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc @@ -15,6 +15,7 @@ */ #include "minddata/dataset/core/de_tensor.h" +#include "minddata/dataset/core/device_tensor.h" #include "minddata/dataset/core/constants.h" #include "minddata/dataset/core/data_type.h" #include "minddata/dataset/include/type_id.h" @@ -35,7 +36,27 @@ DETensor::DETensor(std::shared_ptr tensor_impl) : tensor_impl_(tensor_impl), name_("MindDataTensor"), type_(static_cast(DETypeToMSType(tensor_impl_->type()))), - shape_(tensor_impl_->shape().AsVector()) {} + shape_(tensor_impl_->shape().AsVector()), + is_device_(false) {} + +#ifndef ENABLE_ANDROID +DETensor::DETensor(std::shared_ptr device_tensor_impl, bool is_device) + : device_tensor_impl_(device_tensor_impl), name_("MindDataDeviceTensor"), is_device_(is_device) { + // The sequence of shape_ is (width, widthStride, height, heightStride) in Dvpp module + // We need to add [1]widthStride and [3]heightStride, which are actual YUV image shape, into shape_ attribute + uint8_t flag = 0; + for (auto &i : device_tensor_impl->GetYuvStrideShape()) { + if (flag % 2 == 1) { + int64_t j = static_cast(i); + shape_.emplace_back(j); + } + ++flag; + } + std::reverse(shape_.begin(), shape_.end()); + MS_LOG(INFO) << "This is a YUV420 format image, one pixel takes 1.5 bytes. Therefore, the shape of" + << " image is in (H, W) format. You can search for more information about YUV420 format"; +} +#endif const std::string &DETensor::Name() const { return name_; } @@ -45,6 +66,12 @@ enum mindspore::DataType DETensor::DataType() const { } size_t DETensor::DataSize() const { +#ifndef ENABLE_ANDROID + if (is_device_) { + ASSERT_NULL(device_tensor_impl_); + return device_tensor_impl_->DeviceDataSize(); + } +#endif ASSERT_NULL(tensor_impl_); return tensor_impl_->SizeInBytes(); } @@ -52,6 +79,11 @@ size_t DETensor::DataSize() const { const std::vector &DETensor::Shape() const { return shape_; } std::shared_ptr DETensor::Data() const { +#ifndef ENABLE_ANDROID + if (is_device_) { + return std::shared_ptr(device_tensor_impl_->GetDeviceBuffer(), [](const void *) {}); + } +#endif return std::shared_ptr(tensor_impl_->GetBuffer(), [](const void *) {}); } @@ -60,7 +92,7 @@ void *DETensor::MutableData() { return tensor_impl_->GetMutableBuffer(); } -bool DETensor::IsDevice() const { return false; } +bool DETensor::IsDevice() const { return is_device_; } std::shared_ptr DETensor::Clone() const { return std::make_shared(tensor_impl_); } } // namespace dataset diff --git a/mindspore/ccsrc/minddata/dataset/core/de_tensor.h b/mindspore/ccsrc/minddata/dataset/core/de_tensor.h index 2fe575123f..65b733404a 100644 --- a/mindspore/ccsrc/minddata/dataset/core/de_tensor.h +++ b/mindspore/ccsrc/minddata/dataset/core/de_tensor.h @@ -31,7 +31,9 @@ class DETensor : public mindspore::MSTensor::Impl { DETensor() = default; ~DETensor() override = default; explicit DETensor(std::shared_ptr tensor_impl); - +#ifndef ENABLE_ANDROID + explicit DETensor(std::shared_ptr device_tensor_impl, bool is_device); +#endif const std::string &Name() const override; enum mindspore::DataType DataType() const override; @@ -50,6 +52,10 @@ class DETensor : public mindspore::MSTensor::Impl { private: std::shared_ptr tensor_impl_; +#ifndef ENABLE_ANDROID + std::shared_ptr device_tensor_impl_; +#endif + bool is_device_; std::string name_; enum mindspore::DataType type_; std::vector shape_; diff --git a/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc b/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc new file mode 100644 index 0000000000..618ff90e12 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc @@ -0,0 +1,77 @@ +/** + * Copyright 2021 Huawei Technologies 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 "minddata/dataset/core/global_context.h" +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/core/device_tensor.h" + +namespace mindspore { +namespace dataset { +Status DeviceTensor::SetYuvStrideShape_(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height, + const uint32_t &heightStride) { + YUV_shape_ = {width, widthStride, height, heightStride}; + return Status::OK(); +} + +std::vector DeviceTensor::GetYuvStrideShape() { return YUV_shape_; } + +#ifdef ENABLE_ACL +Status DeviceTensor::SetAttributes(const std::shared_ptr &data_ptr) { + device_data_ = data_ptr->data; + CHECK_FAIL_RETURN_UNEXPECTED(device_data_ != nullptr, "Fail to get the device data."); + SetSize_(data_ptr->dataSize); + SetYuvStrideShape_(data_ptr->width, data_ptr->widthStride, data_ptr->height, data_ptr->heightStride); + return Status::OK(); +} +#endif + +DeviceTensor::DeviceTensor(const TensorShape &shape, const DataType &type) : Tensor(shape, type) { + // grab the mem pool from global context and create the allocator for char data area + std::shared_ptr global_pool = GlobalContext::Instance()->mem_pool(); + data_allocator_ = std::make_unique>(global_pool); +} + +Status DeviceTensor::CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr *out) { + CHECK_FAIL_RETURN_UNEXPECTED(shape.known(), "Invalid shape."); + CHECK_FAIL_RETURN_UNEXPECTED(type != DataType::DE_UNKNOWN, "Invalid data type."); + const DeviceTensorAlloc *alloc = GlobalContext::Instance()->device_tensor_allocator(); + *out = std::allocate_shared(*alloc, shape, type); + // if it's a string tensor and it has no elements, Just initialize the shape and type. + if (!type.IsNumeric() && shape.NumOfElements() == 0) { + return Status::OK(); + } + + CHECK_FAIL_RETURN_UNEXPECTED(type.IsNumeric(), "Number of elements is not 0. The type should be numeric."); + + int64_t byte_size = (*out)->SizeInBytes(); + + // Don't allocate if we have a tensor with no elements. + if (byte_size != 0) { + RETURN_IF_NOT_OK((*out)->AllocateBuffer(byte_size)); + } + return Status::OK(); +} + +uint8_t *DeviceTensor::GetDeviceBuffer() { return device_data_; } + +uint32_t DeviceTensor::DeviceDataSize() { return size_; } + +Status DeviceTensor::SetSize_(const uint32_t &new_size) { + size_ = new_size; + return Status::OK(); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/core/device_tensor.h b/mindspore/ccsrc/minddata/dataset/core/device_tensor.h new file mode 100644 index 0000000000..445dcb1e24 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/core/device_tensor.h @@ -0,0 +1,65 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_DEVICE_TENSOR_H +#define MINDSPORE_DEVICE_TENSOR_H +#include +#include +#include +#include "include/api/status.h" +#include "minddata/dataset/core/tensor.h" +#ifdef ENABLE_ACL +#include "minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h" +#endif +#include "minddata/dataset/core/constants.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class Tensor; +class DeviceTensor : public Tensor { + public: + DeviceTensor(const TensorShape &shape, const DataType &type); + + ~DeviceTensor() {} +#ifdef ENABLE_ACL + Status SetAttributes(const std::shared_ptr &data); +#endif + static Status CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr *out); + + uint8_t *GetDeviceBuffer(); + + std::vector GetYuvStrideShape(); + + uint32_t DeviceDataSize(); + + bool HasDeviceData() { return device_data_ != nullptr; } + + private: + Status SetSize_(const uint32_t &new_size); + + Status SetYuvStrideShape_(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height, + const uint32_t &heightStride); + + std::vector YUV_shape_; + uint8_t *device_data_; + uint32_t size_; +}; + +} // namespace dataset +} // namespace mindspore +#endif // MINDSPORE_DEVICE_TENSOR_H diff --git a/mindspore/ccsrc/minddata/dataset/core/global_context.cc b/mindspore/ccsrc/minddata/dataset/core/global_context.cc index 4920bef0e6..71b58ffe44 100644 --- a/mindspore/ccsrc/minddata/dataset/core/global_context.cc +++ b/mindspore/ccsrc/minddata/dataset/core/global_context.cc @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2021 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ #ifndef ENABLE_ANDROID #include "minddata/dataset/core/cv_tensor.h" #endif +#include "minddata/dataset/core/device_tensor.h" #include "minddata/dataset/core/tensor.h" #include "minddata/dataset/util/allocator.h" #include "minddata/dataset/util/circular_pool.h" @@ -61,6 +62,7 @@ Status GlobalContext::Init() { #ifndef ENABLE_ANDROID cv_tensor_allocator_ = std::make_unique>(mem_pool_); #endif + device_tensor_allocator_ = std::make_unique>(mem_pool_); int_allocator_ = std::make_unique(mem_pool_); return Status::OK(); } diff --git a/mindspore/ccsrc/minddata/dataset/core/global_context.h b/mindspore/ccsrc/minddata/dataset/core/global_context.h index bf8c92cc11..5cd8b71e6e 100644 --- a/mindspore/ccsrc/minddata/dataset/core/global_context.h +++ b/mindspore/ccsrc/minddata/dataset/core/global_context.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2021 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,10 @@ #include #include +#include "include/api/status.h" #include "minddata/dataset/core/config_manager.h" #include "minddata/dataset/core/constants.h" #include "minddata/dataset/util/allocator.h" -#include "minddata/dataset/util/status.h" namespace mindspore { namespace dataset { @@ -30,9 +30,11 @@ namespace dataset { class MemoryPool; class Tensor; class CVTensor; +class DeviceTensor; -using TensorAlloc = Allocator; // An allocator for Tensors -using CVTensorAlloc = Allocator; // An allocator CVTensors +using TensorAlloc = Allocator; // An allocator for Tensors +using CVTensorAlloc = Allocator; // An allocator CVTensors +using DeviceTensorAlloc = Allocator; // An allocator for Device_Tensors using IntAlloc = Allocator; class GlobalContext { @@ -82,6 +84,10 @@ class GlobalContext { // @return the CVTensor allocator as raw pointer const CVTensorAlloc *cv_tensor_allocator() const { return cv_tensor_allocator_.get(); } + // Getter method + // @return the DeviceTensor allocator as raw pointer + const DeviceTensorAlloc *device_tensor_allocator() const { return device_tensor_allocator_.get(); } + // Getter method // @return the integer allocator as raw pointer const IntAlloc *int_allocator() const { return int_allocator_.get(); } @@ -95,12 +101,13 @@ class GlobalContext { Status Init(); static std::once_flag init_instance_flag_; - static std::unique_ptr global_context_; // The instance of the singleton (global) - std::shared_ptr mem_pool_; // A global memory pool - std::shared_ptr config_manager_; // The configs - std::unique_ptr tensor_allocator_; // An allocator for Tensors - std::unique_ptr cv_tensor_allocator_; // An allocator for CV Tensors - std::unique_ptr int_allocator_; // An allocator for ints + static std::unique_ptr global_context_; // The instance of the singleton (global) + std::shared_ptr mem_pool_; // A global memory pool + std::shared_ptr config_manager_; // The configs + std::unique_ptr tensor_allocator_; // An allocator for Tensors + std::unique_ptr cv_tensor_allocator_; // An allocator for CV Tensors + std::unique_ptr device_tensor_allocator_; // An allocator for Device Tensors + std::unique_ptr int_allocator_; // An allocator for ints }; } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/core/tensor.h b/mindspore/ccsrc/minddata/dataset/core/tensor.h index 8603ce8ad2..0b9b5ebfee 100644 --- a/mindspore/ccsrc/minddata/dataset/core/tensor.h +++ b/mindspore/ccsrc/minddata/dataset/core/tensor.h @@ -423,6 +423,17 @@ class Tensor { static Status GetBufferInfo(Tensor *t, py::buffer_info *out); #endif +#ifdef ENABLE_ACL + Status SetYuvShape(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height, + const uint32_t &heightStride) { + std::vector tmp{width, widthStride, height, heightStride}; + yuv_shape_ = tmp; + return Status::OK(); + } + + std::vector GetYuvShape() { return yuv_shape_; } +#endif + /// TensorIterator is a linear iterator that can be used to iterate over the elements of the Tensor /// The order elements is as the memory layout (i.e., row-major) [[1,2,3],[4,5,6] --> 1,2,3,4,5,6 /// \tparam T type of values in the Tensor Iterator @@ -686,6 +697,11 @@ class Tensor { /// pointer to the end of the physical data unsigned char *data_end_ = nullptr; +#ifdef ENABLE_ACL + /// shape for interpretation of YUV image + std::vector yuv_shape_; +#endif + private: friend class DETensor; diff --git a/mindspore/ccsrc/minddata/dataset/include/execute.h b/mindspore/ccsrc/minddata/dataset/include/execute.h index c2c4ace8c7..986c42e5c8 100644 --- a/mindspore/ccsrc/minddata/dataset/include/execute.h +++ b/mindspore/ccsrc/minddata/dataset/include/execute.h @@ -17,25 +17,28 @@ #ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_EXECUTE_H_ #define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_EXECUTE_H_ +#include #include #include +#include "include/api/context.h" #include "include/api/types.h" #include "minddata/dataset/include/constants.h" #include "minddata/dataset/include/transforms.h" namespace mindspore { namespace dataset { +class AscendResource; // Class to manage the resource of Ascend310 // class to run tensor operations in eager mode class Execute { public: /// \brief Constructor - explicit Execute(std::shared_ptr op); + explicit Execute(std::shared_ptr op, std::string deviceType = "CPU"); - explicit Execute(std::vector> ops); + explicit Execute(std::vector> ops, std::string deviceType = "CPU"); /// \brief Destructor - ~Execute() = default; + ~Execute(); /// \brief callable function to execute the TensorOperation in eager mode /// \param[in] input Tensor to be transformed @@ -48,9 +51,19 @@ class Execute { /// \param[out] out Result tensor after transform /// \return - Status Status operator()(const std::vector &input_tensor_list, std::vector *out); +#ifdef ENABLE_ACL + Status DeviceMemoryRelease(); +#endif private: + Status validate_device_(); + std::vector> ops_; + + std::string device_type_; +#ifdef ENABLE_ACL + std::shared_ptr D_resource_; +#endif }; } // namespace dataset diff --git a/mindspore/ccsrc/minddata/dataset/include/vision.h b/mindspore/ccsrc/minddata/dataset/include/vision.h index c9649e2d84..4a5cb002ef 100644 --- a/mindspore/ccsrc/minddata/dataset/include/vision.h +++ b/mindspore/ccsrc/minddata/dataset/include/vision.h @@ -39,7 +39,6 @@ class AutoContrastOperation; class BoundingBoxAugmentOperation; class CutMixBatchOperation; class CutOutOperation; -class DvppDecodeResizeCropOperation; class EqualizeOperation; class HwcToChwOperation; class InvertOperation; @@ -106,22 +105,6 @@ std::shared_ptr CutMixBatch(ImageBatchFormat image_batch_f /// \return Shared pointer to the current TensorOp std::shared_ptr CutOut(int32_t length, int32_t num_patches = 1); -/// \brief Function to create a DvppDecodeResizeCropJpeg TensorOperation. -/// \notes Tensor operation to decode and resize JPEG image using the simulation algorithm of Ascend series -/// chip DVPP module. It is recommended to use this algorithm in the following scenarios: -/// When training, the DVPP of the Ascend chip is not used, -/// and the DVPP of the Ascend chip is used during inference, -/// and the accuracy of inference is lower than the accuracy of training; -/// and the input image size should be in range [16*16, 4096*4096]. -/// Only images with an even resolution can be output. The output of odd resolution is not supported. -/// \param[in] crop vector representing the output size of the final crop image. -/// \param[in] size A vector representing the output size of the intermediate resized image. -/// If size is a single value, smaller edge of the image will be resized to this value with -/// the same image aspect ratio. If size has 2 values, it should be (height, width). -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr DvppDecodeResizeCropJpeg(std::vector crop = {224, 224}, - std::vector resize = {256, 256}); - /// \brief Function to create a Equalize TensorOperation. /// \notes Apply histogram equalization on input image. /// \return Shared pointer to the current TensorOperation. diff --git a/mindspore/ccsrc/minddata/dataset/include/vision_ascend.h b/mindspore/ccsrc/minddata/dataset/include/vision_ascend.h new file mode 100644 index 0000000000..b168d66b76 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/include/vision_ascend.h @@ -0,0 +1,219 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_ASCEND_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_ASCEND_H_ + +#include +#include +#include +#include +#include +#include "include/api/status.h" +#include "minddata/dataset/include/constants.h" +#include "minddata/dataset/include/transforms.h" + +namespace mindspore { +namespace dataset { + +// Transform operations for performing computer vision. +namespace vision { + +// Char arrays storing name of corresponding classes (in alphabetical order) +constexpr char kDvppCropJpegOperation[] = "DvppCropJpeg"; +constexpr char kDvppDecodeResizeOperation[] = "DvppDecodeResize"; +constexpr char kDvppDecodeResizeCropOperation[] = "DvppDecodeResizeCrop"; +constexpr char kDvppDecodeJpegOperation[] = "DvppDecodeJpeg"; +constexpr char kDvppDecodePngOperation[] = "DvppDecodePng"; +constexpr char kDvppResizeJpegOperation[] = "DvppResizeJpeg"; + +class DvppCropJpegOperation; +class DvppDecodeResizeOperation; +class DvppDecodeResizeCropOperation; +class DvppDecodeJpegOperation; +class DvppDecodePngOperation; +class DvppResizeJpegOperation; + +/// \brief Function to create a DvppCropJpeg TensorOperation. +/// \notes Tensor operation to crop JPEG image using the simulation algorithm of Ascend series +/// chip DVPP module. It is recommended to use this algorithm in the following scenarios: +/// When training, the DVPP of the Ascend chip is not used, +/// and the DVPP of the Ascend chip is used during inference, +/// and the accuracy of inference is lower than the accuracy of training; +/// and the input image size should be in range [32*32, 2048*2048]. +/// Only images with an even resolution can be output. The output of odd resolution is not supported. +/// \param[in] crop vector representing the output size of the final crop image. +/// \param[in] size A vector representing the output size of the intermediate resized image. +/// If size is a single value, the shape will be a square. If size has 2 values, it should be (height, width). +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr DvppCropJpeg(std::vector crop = {256, 256}); + +/// \brief Function to create a DvppDecodeResizeJpeg TensorOperation. +/// \notes Tensor operation to decode and resize JPEG image using the simulation algorithm of Ascend series +/// chip DVPP module. It is recommended to use this algorithm in the following scenarios: +/// When training, the DVPP of the Ascend chip is not used, +/// and the DVPP of the Ascend chip is used during inference, +/// and the accuracy of inference is lower than the accuracy of training; +/// and the input image size should be in range [32*32, 2048*2048]. +/// Only images with an even resolution can be output. The output of odd resolution is not supported. +/// \param[in] crop vector representing the output size of the final crop image. +/// \param[in] size A vector representing the output size of the intermediate resized image. +/// If size is a single value, smaller edge of the image will be resized to this value with +/// the same image aspect ratio. If size has 2 values, it should be (height, width). +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr DvppDecodeResizeJpeg(std::vector resize = {256, 256}); + +/// \brief Function to create a DvppDecodeResizeCropJpeg TensorOperation. +/// \notes Tensor operation to decode and resize JPEG image using the simulation algorithm of Ascend series +/// chip DVPP module. It is recommended to use this algorithm in the following scenarios: +/// When training, the DVPP of the Ascend chip is not used, +/// and the DVPP of the Ascend chip is used during inference, +/// and the accuracy of inference is lower than the accuracy of training; +/// and the input image size should be in range [32*32, 2048*2048]. +/// Only images with an even resolution can be output. The output of odd resolution is not supported. +/// \param[in] crop vector representing the output size of the final crop image. +/// \param[in] Resize vector representing the output size of the intermediate resized image. +/// If size is a single value, smaller edge of the image will be resized to the value with +/// the same image aspect ratio. If size has 2 values, it should be (height, width). +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr DvppDecodeResizeCropJpeg(std::vector crop = {224, 224}, + std::vector resize = {256, 256}); + +/// \brief Function to create a DvppDecodeJpeg TensorOperation. +/// \notes Tensor operation to decode JPEG image using the simulation algorithm of Ascend series +/// chip DVPP module. It is recommended to use this algorithm in the following scenarios: +/// When training, the DVPP of the Ascend chip is not used, +/// and the DVPP of the Ascend chip is used during inference, +/// and the accuracy of inference is lower than the accuracy of training; +/// and the input image size should be in range [32*32, 2048*2048]. +/// Only images with an even resolution can be output. The output of odd resolution is not supported. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr DvppDecodeJpeg(); + +/// \brief Function to create a DvppDecodePng TensorOperation. +/// \notes Tensor operation to decode PNG image using the simulation algorithm of Ascend series +/// chip DVPP module. It is recommended to use this algorithm in the following scenarios: +/// When training, the DVPP of the Ascend chip is not used, +/// and the DVPP of the Ascend chip is used during inference, +/// and the accuracy of inference is lower than the accuracy of training; +/// and the input image size should be in range [32*32, 2048*2048]. +/// Only images with an even resolution can be output. The output of odd resolution is not supported. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr DvppDecodePng(); + +/// \brief Function to create a DvppResizeJpeg TensorOperation. +/// \notes Tensor operation to resize JPEG image using Ascend series chip DVPP module. +/// It is recommended to use this algorithm in the following scenarios: +/// When training, the DVPP of the Ascend chip is not used, +/// and the DVPP of the Ascend chip is used during inference, +/// and the accuracy of inference is lower than the accuracy of training; +/// and the input image size should be in range [32*32, 2048*2048]. +/// Only images with an even resolution can be output. The output of odd resolution is not supported. +/// \param[in] resize vector represents the shape of image after resize. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr DvppResizeJpeg(std::vector resize = {256, 256}); + +class DvppCropJpegOperation : public TensorOperation { + public: + explicit DvppCropJpegOperation(const std::vector &resize); + + ~DvppCropJpegOperation() = default; + + std::shared_ptr Build() override; + + Status ValidateParams() override; + + std::string Name() const override { return kDvppCropJpegOperation; } + + private: + std::vector crop_; +}; + +class DvppDecodeResizeOperation : public TensorOperation { + public: + explicit DvppDecodeResizeOperation(const std::vector &resize); + + ~DvppDecodeResizeOperation() = default; + + std::shared_ptr Build() override; + + Status ValidateParams() override; + + std::string Name() const override { return kDvppDecodeResizeOperation; } + + private: + std::vector resize_; +}; + +class DvppDecodeResizeCropOperation : public TensorOperation { + public: + explicit DvppDecodeResizeCropOperation(const std::vector &crop, const std::vector &resize); + + ~DvppDecodeResizeCropOperation() = default; + + std::shared_ptr Build() override; + + Status ValidateParams() override; + + std::string Name() const override { return kDvppDecodeResizeCropOperation; } + + private: + std::vector crop_; + std::vector resize_; +}; + +class DvppDecodeJpegOperation : public TensorOperation { + public: + ~DvppDecodeJpegOperation() = default; + + std::shared_ptr Build() override; + + Status ValidateParams() override; + + std::string Name() const override { return kDvppDecodeJpegOperation; } +}; + +class DvppDecodePngOperation : public TensorOperation { + public: + ~DvppDecodePngOperation() = default; + + std::shared_ptr Build() override; + + Status ValidateParams() override; + + std::string Name() const override { return kDvppDecodePngOperation; } +}; + +class DvppResizeJpegOperation : public TensorOperation { + public: + explicit DvppResizeJpegOperation(const std::vector &resize); + + ~DvppResizeJpegOperation() = default; + + std::shared_ptr Build() override; + + Status ValidateParams() override; + + std::string Name() const override { return kDvppResizeJpegOperation; } + + private: + std::vector resize_; +}; +} // namespace vision +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_ASCEND_H_ diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/CMakeLists.txt b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/CMakeLists.txt index e531e4d9ee..bd7696d63f 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/CMakeLists.txt +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/CMakeLists.txt @@ -2,5 +2,10 @@ file(GLOB_RECURSE _CURRENT_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc" set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD) add_subdirectory(utils) add_library(kernels-dvpp-image OBJECT - dvpp_decode_resize_crop_jpeg_op.cc) + dvpp_crop_jpeg_op.cc + dvpp_decode_resize_crop_jpeg_op.cc + dvpp_decode_resize_jpeg_op.cc + dvpp_decode_jpeg_op.cc + dvpp_resize_jpeg_op.cc + dvpp_decode_png_op.cc) add_dependencies(kernels-dvpp-image dvpp-utils) \ No newline at end of file diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.cc new file mode 100644 index 0000000000..48907d0f5f --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.cc @@ -0,0 +1,145 @@ +/** + * Copyright 2021 Huawei Technologies 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 "include/api/context.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/device_tensor.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h" +#include "minddata/dataset/kernels/image/image_utils.h" + +namespace mindspore { +namespace dataset { +Status DvppCropJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer is empty."); + std::string last_step = "Resize"; + std::shared_ptr imageinfo(processor_->Get_Resized_DeviceData()); + if (!imageinfo->data) { + last_step = "Decode"; + } + APP_ERROR ret = processor_->JPEG_C(last_step); + if (ret != APP_ERR_OK) { + processor_->Release(); + std::string error = "Error in dvpp crop processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + std::shared_ptr CropOut(processor_->Get_Croped_DeviceData()); + const TensorShape dvpp_shape({1, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output); + (*output)->SetAttributes(CropOut); + if (!((*output)->HasDeviceData())) { + std::string error = "[ERROR] Fail to get the Output result from device memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppCropJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppCropJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty."); + unsigned char *buffer = const_cast(input->GetBuffer()); + DvppDataInfo imageinfo; + imageinfo.dataSize = input->SizeInBytes(); + imageinfo.data = static_cast(buffer); + std::vector yuv_shape_ = input->GetYuvShape(); + imageinfo.width = yuv_shape_[0]; + imageinfo.widthStride = yuv_shape_[1]; + imageinfo.height = yuv_shape_[2]; + imageinfo.heightStride = yuv_shape_[3]; + imageinfo.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; + ResourceInfo resource; + resource.aclConfigPath = ""; + resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); + std::shared_ptr instance = ResourceManager::GetInstance(); + APP_ERROR ret = instance->InitResource(resource); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init D-chip:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + int deviceId = *(resource.deviceIds.begin()); + aclrtContext context = instance->GetContext(deviceId); + // Second part end where we initialize the resource of D-chip and set up all configures + MDAclProcess process(crop_width_, crop_height_, context, true); + ret = process.InitResource(); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init resource:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + ret = process.JPEG_C(imageinfo); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in dvpp crop processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + // Third part end where we execute the core function of dvpp + auto data = std::static_pointer_cast(process.Get_Memory_Data()); + unsigned char *ret_ptr = data.get(); + std::shared_ptr CropOut(process.Get_Croped_DeviceData()); + dsize_t dvpp_length = CropOut->dataSize; + const TensorShape dvpp_shape({dvpp_length, 1, 1}); + uint32_t crop_height = CropOut->height; + uint32_t crop_heightStride = CropOut->heightStride; + uint32_t crop_width = CropOut->width; + uint32_t crop_widthStride = CropOut->widthStride; + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output); + (*output)->SetYuvShape(crop_width, crop_widthStride, crop_height, crop_heightStride); + if (!((*output)->HasData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + process.device_memory_release(); + process.Release(); + // Last part end where we transform the processed data into a tensor which can be applied in later units. + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppCropJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppCropJpegOp::OutputShape(const std::vector &inputs, std::vector &outputs) { + RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); + outputs.clear(); + TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 1 channels + if (inputs[0].Rank() == 1) outputs.emplace_back(out); + if (!outputs.empty()) return Status::OK(); + return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape"); +} + +Status DvppCropJpegOp::SetAscendResource(const std::shared_ptr &processor) { + processor_ = processor; + processor_->SetCropParas(crop_width_, crop_height_); + return Status::OK(); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h new file mode 100644 index 0000000000..8fa94f8d5d --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_CROP_JPEG_OP_H +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_CROP_JPEG_OP_H + +#include +#include +#include + +#include "acl/acl.h" +#include "mindspore/core/utils/log_adapter.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/device_tensor.h" +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class DvppCropJpegOp : public TensorOp { + public: + DvppCropJpegOp(int32_t crop_height, int32_t crop_width) : crop_height_(crop_height), crop_width_(crop_width) {} + + /// \brief Destructor + ~DvppCropJpegOp() = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; + + std::string Name() const override { return kDvppCropJpegOp; } + + Status SetAscendResource(const std::shared_ptr &processor) override; + + private: + uint32_t crop_height_; + uint32_t crop_width_; + + std::shared_ptr processor_; +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_CROP_JPEG_OP_H diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.cc new file mode 100644 index 0000000000..2ddc4dddd5 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.cc @@ -0,0 +1,139 @@ +/** + * Copyright 2021 Huawei Technologies 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 "include/api/context.h" +#include "minddata/dataset/core/cv_tensor.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/device_tensor.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/image_utils.h" + +namespace mindspore { +namespace dataset { +// Compute() will be called when context=="Ascend310" +Status DvppDecodeJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty"); + APP_ERROR ret = processor_->JPEG_D(); + if (ret != APP_ERR_OK) { + processor_->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + std::shared_ptr DecodeOut(processor_->Get_Decode_DeviceData()); + const TensorShape dvpp_shape({1, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output); + (*output)->SetAttributes(DecodeOut); + if (!((*output)->HasDeviceData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} +// Compute() will be called when context=="CPU" +Status DvppDecodeJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + if (!IsNonEmptyJPEG(input)) { + RETURN_STATUS_UNEXPECTED("DvppDecodeJpegOp only support process JPEG image."); + } + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty."); + unsigned char *buffer = const_cast(input->GetBuffer()); + RawData imageInfo; + uint32_t filesize = input->SizeInBytes(); + imageInfo.lenOfByte = filesize; + imageInfo.data = static_cast(buffer); + ResourceInfo resource; + resource.aclConfigPath = ""; + resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); + std::shared_ptr instance = ResourceManager::GetInstance(); + APP_ERROR ret = instance->InitResource(resource); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init D-chip:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + int deviceId = *(resource.deviceIds.begin()); + aclrtContext context = instance->GetContext(deviceId); + // Second part end where we initialize the resource of D-chip and set up all configures + MDAclProcess process(context, false); + ret = process.InitResource(); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init resource:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + ret = process.JPEG_D(imageInfo); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + // Third part end where we execute the core function of dvpp + auto data = std::static_pointer_cast(process.Get_Memory_Data()); + unsigned char *ret_ptr = data.get(); + std::shared_ptr DecodeOut(process.Get_Decode_DeviceData()); + dsize_t dvpp_length = DecodeOut->dataSize; + uint32_t decoded_height = DecodeOut->height; + uint32_t decoded_heightStride = DecodeOut->heightStride; + uint32_t decoded_width = DecodeOut->width; + uint32_t decoded_widthStride = DecodeOut->widthStride; + // std::cout << "Decoded size: " << decoded_width << ", " << decoded_height << std::endl; + const TensorShape dvpp_shape({dvpp_length, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output); + (*output)->SetYuvShape(decoded_width, decoded_widthStride, decoded_height, decoded_heightStride); + if (!((*output)->HasData())) { + std::string error = "[ERROR] Fail to get the Output result from device memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + process.device_memory_release(); + process.Release(); + // Last part end where we transform the processed data into a tensor which can be applied in later units. + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppDecodeJpegOp::SetAscendResource(const std::shared_ptr &processor) { + processor_ = processor; + return Status::OK(); +} + +Status DvppDecodeJpegOp::OutputShape(const std::vector &inputs, std::vector &outputs) { + RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); + outputs.clear(); + TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 3 channels + if (inputs[0].Rank() == 1) outputs.emplace_back(out); + if (!outputs.empty()) return Status::OK(); + return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape"); +} + +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h new file mode 100644 index 0000000000..b616ea9d55 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h @@ -0,0 +1,59 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_JPEG_OP_H +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_JPEG_OP_H + +#include +#include +#include + +#include "acl/acl.h" +#include "mindspore/core/utils/log_adapter.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class DvppDecodeJpegOp : public TensorOp { + public: + DvppDecodeJpegOp() { processor_ = nullptr; } + + /// \brief Destructor + ~DvppDecodeJpegOp() = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; + + std::string Name() const override { return kDvppDecodeJpegOp; } + + Status SetAscendResource(const std::shared_ptr &processor) override; + + private: + std::shared_ptr processor_; +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_JPEG_OP_H diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.cc new file mode 100644 index 0000000000..881fc78eb8 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.cc @@ -0,0 +1,138 @@ +/** + * Copyright 2021 Huawei Technologies 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 "include/api/context.h" +#include "minddata/dataset/core/cv_tensor.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/image_utils.h" + +namespace mindspore { +namespace dataset { +Status DvppDecodePngOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty"); + APP_ERROR ret = processor_->PNG_D(); + if (ret != APP_ERR_OK) { + processor_->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + std::shared_ptr DecodeOut(processor_->Get_Decode_DeviceData()); + const TensorShape dvpp_shape({1, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output); + (*output)->SetAttributes(DecodeOut); + if (!((*output)->HasDeviceData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppDecodePngOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + if (!IsNonEmptyPNG(input)) { + RETURN_STATUS_UNEXPECTED("DvppDecodePngOp only support process PNG image."); + } + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty."); + unsigned char *buffer = const_cast(input->GetBuffer()); + RawData imageInfo; + uint32_t filesize = input->SizeInBytes(); + imageInfo.lenOfByte = filesize; + imageInfo.data = static_cast(buffer); + ResourceInfo resource; + resource.aclConfigPath = ""; + resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); + std::shared_ptr instance = ResourceManager::GetInstance(); + APP_ERROR ret = instance->InitResource(resource); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init D-chip:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + int deviceId = *(resource.deviceIds.begin()); + aclrtContext context = instance->GetContext(deviceId); + // Second part end where we initialize the resource of D-chip and set up all configures + MDAclProcess process(context, false); + ret = process.InitResource(); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init resource:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + ret = process.PNG_D(imageInfo); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + // Third part end where we execute the core function of dvpp + /* 测试Device内存 + */ + auto data = std::static_pointer_cast(process.Get_Memory_Data()); + unsigned char *ret_ptr = data.get(); + std::shared_ptr DecodeOut(process.Get_Decode_DeviceData()); + dsize_t dvpp_length = DecodeOut->dataSize; + // dsize_t decode_height = DecodeOut->height; + // dsize_t decode_width = DecodeOut->width; + const TensorShape dvpp_shape({dvpp_length, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output); + if (!((*output)->HasData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + process.device_memory_release(); + process.Release(); + // Last part end where we transform the processed data into a tensor which can be applied in later units. + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodePngOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppDecodePngOp::OutputShape(const std::vector &inputs, std::vector &outputs) { + RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); + outputs.clear(); + TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 3 channels + if (inputs[0].Rank() == 1) outputs.emplace_back(out); + if (!outputs.empty()) return Status::OK(); + return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape"); +} + +Status DvppDecodePngOp::SetAscendResource(const std::shared_ptr &processor) { + processor_ = processor; + return Status::OK(); +} + +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h new file mode 100644 index 0000000000..b53605fa91 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h @@ -0,0 +1,58 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_PNG_OP_H +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_PNG_OP_H + +#include +#include +#include + +#include "acl/acl.h" +#include "mindspore/core/utils/log_adapter.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class DvppDecodePngOp : public TensorOp { + public: + DvppDecodePngOp() {} + + /// \brief Destructor + ~DvppDecodePngOp() = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; + + std::string Name() const override { return kDvppDecodePngOp; } + + Status SetAscendResource(const std::shared_ptr &processor) override; + + private: + std::shared_ptr processor_; +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_PNG_OP_H diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.cc index 080c6fbd3d..244e47a04a 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.cc @@ -17,20 +17,48 @@ #include #include #include -#include "minddata/dataset/kernels/image/dvpp/utils/AclProcess.h" +#include "include/api/context.h" #include "minddata/dataset/core/cv_tensor.h" -#include "minddata/dataset/kernels/image/image_utils.h" -#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" #include "minddata/dataset/core/data_type.h" #include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h" -#include "include/api/context.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/image_utils.h" namespace mindspore { namespace dataset { +Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr &input, + std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty"); + APP_ERROR ret = processor_->JPEG_DRC(); + if (ret != APP_ERR_OK) { + processor_->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + std::shared_ptr CropOut(processor_->Get_Croped_DeviceData()); + // std::cout << "Decoded size: " << decoded_width << ", " << decoded_height << std::endl; + const TensorShape dvpp_shape({1, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output); + (*output)->SetAttributes(CropOut); + if (!((*output)->HasDeviceData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodeResizeCropJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { IO_CHECK(input, output); if (!IsNonEmptyJPEG(input)) { - RETURN_STATUS_UNEXPECTED("SoftDvppDecodeReiszeJpegOp only support process jpeg image."); + RETURN_STATUS_UNEXPECTED("DvppDecodeReiszeJpegOp only support process jpeg image."); } try { CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty."); @@ -38,11 +66,7 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr &input, RawData imageInfo; uint32_t filesize = input->SizeInBytes(); imageInfo.lenOfByte = filesize; - imageInfo.data = std::make_shared(); - imageInfo.data.reset(new uint8_t[filesize], std::default_delete()); - memcpy_s(imageInfo.data.get(), filesize, buffer, filesize); - // First part end, whose function is to transform data from a Tensor to imageinfo data structure which can be - // applied on device + imageInfo.data = static_cast(buffer); ResourceInfo resource; resource.aclConfigPath = ""; resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); @@ -56,25 +80,26 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr &input, int deviceId = *(resource.deviceIds.begin()); aclrtContext context = instance->GetContext(deviceId); // Second part end where we initialize the resource of D chip and set up all configures - AclProcess process(resized_width_, resized_height_, crop_width_, crop_height_, context); - process.set_mode(true); - ret = process.InitResource(); + MDAclProcess processor(resized_width_, resized_height_, crop_width_, crop_height_, context, true); + ret = processor.InitResource(); if (ret != APP_ERR_OK) { instance->Release(); std::string error = "Error in Init resource:" + std::to_string(ret); RETURN_STATUS_UNEXPECTED(error); } - ret = process.Process(imageInfo); + + ret = processor.JPEG_DRC(imageInfo); if (ret != APP_ERR_OK) { instance->Release(); std::string error = "Error in dvpp processing:" + std::to_string(ret); RETURN_STATUS_UNEXPECTED(error); } + // Third part end where we execute the core function of dvpp - auto data = std::static_pointer_cast(process.Get_Memory_Data()); + auto data = std::static_pointer_cast(processor.Get_Memory_Data()); unsigned char *ret_ptr = data.get(); - std::shared_ptr CropOut = process.Get_Device_Memory_Data(); - dsize_t dvpp_length = CropOut->dataSize; + std::shared_ptr CropOut(processor.Get_Croped_DeviceData()); + uint32_t dvpp_length = CropOut->dataSize; const TensorShape dvpp_shape({dvpp_length, 1, 1}); const DataType dvpp_data_type(DataType::DE_UINT8); mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output); @@ -82,8 +107,8 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr &input, std::string error = "[ERROR] Fail to get the Output result from memory!"; RETURN_STATUS_UNEXPECTED(error); } - process.device_memory_release(); - process.Release(); + processor.device_memory_release(); + processor.Release(); // Last part end where we transform the processed data into a tensor which can be applied in later units. } catch (const cv::Exception &e) { std::string error = "[ERROR] Fail in DvppDecodeResizeCropJpegOp:" + std::string(e.what()); @@ -102,5 +127,12 @@ Status DvppDecodeResizeCropJpegOp::OutputShape(const std::vector &i return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape"); } +Status DvppDecodeResizeCropJpegOp::SetAscendResource(const std::shared_ptr &processor) { + processor_ = processor; + processor_->SetResizeParas(resized_width_, resized_height_); + processor_->SetCropParas(crop_width_, crop_height_); + return Status::OK(); +} + } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h index 33df9bf499..2e22558699 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h @@ -14,21 +14,21 @@ * limitations under the License. */ -#ifndef MINDSPORE_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H -#define MINDSPORE_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H #include #include #include -#include "minddata/dataset/core/tensor.h" -#include "minddata/dataset/kernels/tensor_op.h" -#include "minddata/dataset/util/status.h" -#include "minddata/dataset/core/data_type.h" +#include "acl/acl.h" #include "mindspore/core/utils/log_adapter.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/tensor.h" #include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" #include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" -#include "acl/acl.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" namespace mindspore { namespace dataset { @@ -44,17 +44,23 @@ class DvppDecodeResizeCropJpegOp : public TensorOp { ~DvppDecodeResizeCropJpegOp() = default; Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; std::string Name() const override { return kDvppDecodeResizeCropJpegOp; } + Status SetAscendResource(const std::shared_ptr &processor) override; + private: int32_t crop_height_; int32_t crop_width_; int32_t resized_height_; int32_t resized_width_; + std::shared_ptr processor_; }; } // namespace dataset } // namespace mindspore -#endif // MINDSPORE_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.cc new file mode 100644 index 0000000000..b7c5909ea6 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.cc @@ -0,0 +1,134 @@ +/** + * Copyright 2021 Huawei Technologies 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 "include/api/context.h" +#include "minddata/dataset/core/cv_tensor.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/image_utils.h" + +namespace mindspore { +namespace dataset { +Status DvppDecodeResizeJpegOp::Compute(const std::shared_ptr &input, + std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty"); + APP_ERROR ret = processor_->JPEG_DR(); + if (ret != APP_ERR_OK) { + processor_->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + std::shared_ptr ResizeOut(processor_->Get_Resized_DeviceData()); + const TensorShape dvpp_shape({1, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output); + (*output)->SetAttributes(ResizeOut); + if (!((*output)->HasDeviceData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodeResizeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppDecodeResizeJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + if (!IsNonEmptyJPEG(input)) { + RETURN_STATUS_UNEXPECTED("DvppDecodeReiszeJpegOp only support process jpeg image."); + } + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty."); + unsigned char *buffer = const_cast(input->GetBuffer()); + RawData imageInfo; + uint32_t filesize = input->SizeInBytes(); + imageInfo.lenOfByte = filesize; + imageInfo.data = static_cast(buffer); + ResourceInfo resource; + resource.aclConfigPath = ""; + resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); + std::shared_ptr instance = ResourceManager::GetInstance(); + APP_ERROR ret = instance->InitResource(resource); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init D-chip:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + int deviceId = *(resource.deviceIds.begin()); + aclrtContext context = instance->GetContext(deviceId); + // Second part end where we initialize the resource of D-chip and set up all configures + MDAclProcess process(resized_width_, resized_height_, context, false); + ret = process.InitResource(); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init resource:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + ret = process.JPEG_DR(imageInfo); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + // Third part end where we execute the core function of dvpp + auto data = std::static_pointer_cast(process.Get_Memory_Data()); + unsigned char *ret_ptr = data.get(); + std::shared_ptr ResizeOut(process.Get_Resized_DeviceData()); + dsize_t dvpp_length = ResizeOut->dataSize; + const TensorShape dvpp_shape({dvpp_length, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output); + if (!((*output)->HasData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + process.device_memory_release(); + process.Release(); + // Last part end where we transform the processed data into a tensor which can be applied in later units. + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppDecodeResizeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppDecodeResizeJpegOp::OutputShape(const std::vector &inputs, std::vector &outputs) { + RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); + outputs.clear(); + TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 1 channels + if (inputs[0].Rank() == 1) outputs.emplace_back(out); + if (!outputs.empty()) return Status::OK(); + return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape"); +} + +Status DvppDecodeResizeJpegOp::SetAscendResource(const std::shared_ptr &processor) { + processor_ = processor; + processor_->SetResizeParas(resized_width_, resized_height_); + return Status::OK(); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h new file mode 100644 index 0000000000..947a4a4584 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H + +#include +#include +#include + +#include "acl/acl.h" +#include "mindspore/core/utils/log_adapter.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class DvppDecodeResizeJpegOp : public TensorOp { + public: + DvppDecodeResizeJpegOp(int32_t resized_height, int32_t resized_width) + : resized_height_(resized_height), resized_width_(resized_width) {} + + /// \brief Destructor + ~DvppDecodeResizeJpegOp() = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; + + std::string Name() const override { return kDvppDecodeResizeJpegOp; } + + Status SetAscendResource(const std::shared_ptr &processor) override; + + private: + int32_t resized_height_; + int32_t resized_width_; + + std::shared_ptr processor_; +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.cc new file mode 100644 index 0000000000..a83fb72b78 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.cc @@ -0,0 +1,147 @@ +/** + * Copyright 2021 Huawei Technologies 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 "include/api/context.h" +#include "minddata/dataset/core/cv_tensor.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/device_tensor.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h" +#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h" +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#include "minddata/dataset/kernels/image/image_utils.h" + +namespace mindspore { +namespace dataset { +Status DvppResizeJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer is empty."); + std::string last_step = "Decode"; + std::shared_ptr imageinfo(processor_->Get_Decode_DeviceData()); + if (!imageinfo->data) { + last_step = "Crop"; + } + APP_ERROR ret = processor_->JPEG_R(last_step); + if (ret != APP_ERR_OK) { + processor_->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + std::shared_ptr ResizeOut(processor_->Get_Resized_DeviceData()); + const TensorShape dvpp_shape({1, 1, 1}); + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output); + (*output)->SetAttributes(ResizeOut); // Set attributes for output DeviceTensor + if (!((*output)->HasDeviceData())) { + std::string error = "[ERROR] Fail to get the Output result from device memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppResizeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppResizeJpegOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + try { + CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty."); + unsigned char *buffer = const_cast(input->GetBuffer()); + DvppDataInfo imageinfo; + imageinfo.dataSize = input->SizeInBytes(); + imageinfo.data = static_cast(buffer); + std::vector yuv_shape_ = input->GetYuvShape(); + imageinfo.width = yuv_shape_[0]; + imageinfo.widthStride = yuv_shape_[1]; + imageinfo.height = yuv_shape_[2]; + imageinfo.heightStride = yuv_shape_[3]; + imageinfo.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; + ResourceInfo resource; + resource.aclConfigPath = ""; + resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID()); + std::shared_ptr instance = ResourceManager::GetInstance(); + APP_ERROR ret = instance->InitResource(resource); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init D-chip:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + int deviceId = *(resource.deviceIds.begin()); + aclrtContext context = instance->GetContext(deviceId); + // Second part end where we initialize the resource of D-chip and set up all configures + MDAclProcess process(resized_width_, resized_height_, context, false); + ret = process.InitResource(); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in Init resource:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + ret = process.JPEG_R(imageinfo); + if (ret != APP_ERR_OK) { + instance->Release(); + std::string error = "Error in dvpp processing:" + std::to_string(ret); + RETURN_STATUS_UNEXPECTED(error); + } + + // Third part end where we execute the core function of dvpp + auto data = std::static_pointer_cast(process.Get_Memory_Data()); + unsigned char *ret_ptr = data.get(); + std::shared_ptr ResizeOut(process.Get_Resized_DeviceData()); + dsize_t dvpp_length = ResizeOut->dataSize; + const TensorShape dvpp_shape({dvpp_length, 1, 1}); + uint32_t resized_height = ResizeOut->height; + uint32_t resized_heightStride = ResizeOut->heightStride; + uint32_t resized_width = ResizeOut->width; + uint32_t resized_widthStride = ResizeOut->widthStride; + const DataType dvpp_data_type(DataType::DE_UINT8); + mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output); + (*output)->SetYuvShape(resized_width, resized_widthStride, resized_height, resized_heightStride); + if (!((*output)->HasData())) { + std::string error = "[ERROR] Fail to get the Output result from memory!"; + RETURN_STATUS_UNEXPECTED(error); + } + process.device_memory_release(); + process.Release(); + // Last part end where we transform the processed data into a tensor which can be applied in later units. + } catch (const cv::Exception &e) { + std::string error = "[ERROR] Fail in DvppResizeJpegOp:" + std::string(e.what()); + RETURN_STATUS_UNEXPECTED(error); + } + return Status::OK(); +} + +Status DvppResizeJpegOp::SetAscendResource(const std::shared_ptr &processor) { + processor_ = processor; + processor_->SetResizeParas(resized_width_, resized_height_); + return Status::OK(); +} + +Status DvppResizeJpegOp::OutputShape(const std::vector &inputs, std::vector &outputs) { + RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); + outputs.clear(); + TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 1 channels + if (inputs[0].Rank() == 1) outputs.emplace_back(out); + if (!outputs.empty()) return Status::OK(); + return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape"); +} + +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h new file mode 100644 index 0000000000..c269abe5e7 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h @@ -0,0 +1,63 @@ +/** + * Copyright 2021 Huawei Technologies 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. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_RESIZE_JPEG_OP_H +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_RESIZE_JPEG_OP_H + +#include +#include +#include + +#include "acl/acl.h" +#include "minddata/dataset/core/data_type.h" +#include "minddata/dataset/core/device_tensor.h" +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h" +#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" +#include "mindspore/core/utils/log_adapter.h" + +namespace mindspore { +namespace dataset { +class DvppResizeJpegOp : public TensorOp { + public: + DvppResizeJpegOp(int32_t resized_height, int32_t resized_width) + : resized_height_(resized_height), resized_width_(resized_width) {} + + /// \brief Destructor + ~DvppResizeJpegOp() = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; + + std::string Name() const override { return kDvppDecodeResizeJpegOp; } + + Status SetAscendResource(const std::shared_ptr &processor) override; + + private: + int32_t resized_height_; + int32_t resized_width_; + + std::shared_ptr processor_; +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_RESIZE_JPEG_OP_H diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.cc deleted file mode 100644 index 31172e8dd9..0000000000 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.cc +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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 "AclProcess.h" -#include -#include -#include - -namespace { -const int BUFFER_SIZE = 2048; -const mode_t DEFAULT_FILE_PERMISSION = 0077; -} // namespace - -mode_t SetFileDefaultUmask() { return umask(DEFAULT_FILE_PERMISSION); } - -/* - * @description: Constructor - * @param: resizeWidth specifies the resized width - * @param: resizeHeight specifies the resized hegiht - * @param: stream is used to maintain the execution order of operations - * @param: context is used to manage the life cycle of objects - * @param: dvppCommon is a class for decoding and resizing - */ -AclProcess::AclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight, - aclrtContext context, aclrtStream stream, std::shared_ptr dvppCommon) - : resizeWidth_(resizeWidth), - resizeHeight_(resizeHeight), - cropWidth_(cropWidth), - cropHeight_(cropHeight), - context_(context), - stream_(stream), - dvppCommon_(dvppCommon) { - repeat_ = true; -} - -/* - * @description: Release AclProcess resources - * @return: aclError which is error code of ACL API - */ -APP_ERROR AclProcess::Release() { - // Release objects resource - APP_ERROR ret = dvppCommon_->DeInit(); - dvppCommon_->ReleaseDvppBuffer(); - - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to deinitialize dvppCommon_, ret = " << ret; - return ret; - } - MS_LOG(INFO) << "dvppCommon_ object deinitialized successfully"; - dvppCommon_.reset(); - - // Release stream - if (stream_ != nullptr) { - ret = aclrtDestroyStream(stream_); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to destroy stream, ret = " << ret; - stream_ = nullptr; - return ret; - } - stream_ = nullptr; - } - MS_LOG(INFO) << "The stream is destroyed successfully"; - return APP_ERR_OK; -} - -/* - * @description: Initialize DvppCommon object - * @return: aclError which is error code of ACL API - */ -APP_ERROR AclProcess::InitModule() { - // Create Dvpp JpegD object - dvppCommon_ = std::make_shared(stream_); - if (dvppCommon_ == nullptr) { - MS_LOG(ERROR) << "Failed to create dvppCommon_ object"; - return APP_ERR_COMM_INIT_FAIL; - } - MS_LOG(INFO) << "DvppCommon object created successfully"; - APP_ERROR ret = dvppCommon_->Init(); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to initialize dvppCommon_ object, ret = " << ret; - return ret; - } - MS_LOG(INFO) << "DvppCommon object initialized successfully"; - return APP_ERR_OK; -} - -/* - * @description: Initialize AclProcess resources - * @return: aclError which is error code of ACL API - */ -APP_ERROR AclProcess::InitResource() { - APP_ERROR ret = aclrtSetCurrentContext(context_); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to get ACL context, ret = " << ret; - return ret; - } - MS_LOG(INFO) << "The context is created successfully"; - ret = aclrtCreateStream(&stream_); // Create stream for application - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to create ACL stream, ret = " << ret; - return ret; - } - MS_LOG(INFO) << "The stream is created successfully"; - // Initialize dvpp module - if (InitModule() != APP_ERR_OK) { - return APP_ERR_COMM_INIT_FAIL; - } - return APP_ERR_OK; -} - -/* - * @description: Read image files, and perform decoding and scaling - * @param: imageFile specifies the image path to be processed - * @return: aclError which is error code of ACL API - */ -APP_ERROR AclProcess::Preprocess(const RawData &ImageInfo) { - // Decode process - APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; - return ret; - } - // Get output of decoded jpeg image - std::shared_ptr decodeOutData = dvppCommon_->GetDecodedImage(); - if (decodeOutData == nullptr) { - MS_LOG(ERROR) << "Decode output buffer is null."; - return APP_ERR_COMM_INVALID_POINTER; - } - // Define output of resize jpeg image - DvppDataInfo resizeOut; - resizeOut.width = resizeWidth_; - resizeOut.height = resizeHeight_; - resizeOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; - // Run resize application function - ret = dvppCommon_->CombineResizeProcess(*(decodeOutData.get()), resizeOut, true); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << "."; - return ret; - } - // Get output of resize jpeg image - std::shared_ptr resizeOutData = dvppCommon_->GetResizedImage(); - if (resizeOutData == nullptr) { - MS_LOG(ERROR) << "resize output buffer is null."; - return APP_ERR_COMM_INVALID_POINTER; - } - // Define output of crop jpeg image - DvppDataInfo cropOut; - cropOut.width = cropWidth_; - cropOut.height = cropHeight_; - cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; - // Define input of crop jpeg image - DvppCropInputInfo cropInfo; - cropInfo.dataInfo = *(resizeOutData.get()); - // Define crop parameters - CropRoiConfig cropCfg; - CropConfigFilter(cropCfg, cropInfo); - ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << "."; - return ret; - } - return APP_ERR_OK; -} - -/* - * @description: Decode and scale the picture, and write the result to a file - * @param: imageFile specifies the image path to be processed - * @return: aclError which is error code of ACL API - */ -APP_ERROR AclProcess::Process(const RawData &ImageInfo) { - struct timeval begin = {0}; - struct timeval end = {0}; - gettimeofday(&begin, nullptr); - // deal with image - APP_ERROR ret = Preprocess(ImageInfo); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to preprocess, ret = " << ret; - return ret; - } - gettimeofday(&end, nullptr); - // Calculate the time cost of preprocess - const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; - const double fps = 1 * SEC2MS / costMs; - MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps; - // Get output of resize module - std::shared_ptr CropOutData = dvppCommon_->GetCropedImage(); - if (CropOutData->dataSize == 0) { - MS_LOG(ERROR) << "CropOutData return NULL"; - return APP_ERR_COMM_INVALID_POINTER; - } - // Alloc host memory for the inference output according to the size of output - void *resHostBuf = nullptr; - ret = aclrtMallocHost(&resHostBuf, CropOutData->dataSize); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; - return ret; - } - std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); - processedInfo_ = outBuf; - // Memcpy the output data from device to host - ret = aclrtMemcpy(outBuf.get(), CropOutData->dataSize, CropOutData->data, CropOutData->dataSize, - ACL_MEMCPY_DEVICE_TO_HOST); - if (ret != APP_ERR_OK) { - MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; - return ret; - } - return APP_ERR_OK; -} - -void AclProcess::CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo) { - cfg.up = (resizeHeight_ - cropHeight_) / 2; - if (cfg.up % 2 != 0) { - cfg.up++; - } - cfg.down = resizeHeight_ - (resizeHeight_ - cropHeight_) / 2; - if (cfg.down % 2 == 0) { - cfg.down--; - } - cfg.left = (resizeWidth_ - cropWidth_) / 2; - if (cfg.left % 2 != 0) { - cfg.left++; - } - cfg.right = resizeWidth_ - (resizeWidth_ - cropWidth_) / 2; - if (cfg.right % 2 == 0) { - cfg.right--; - } - cropinfo.roi = cfg; -} - -/* - * @description: Obtain result data of memory - * @param: processed_data is result data info pointer - * @return: Address of data in the memory - */ -std::shared_ptr AclProcess::Get_Memory_Data() { return processedInfo_; } - -std::shared_ptr AclProcess::Get_Device_Memory_Data() { return dvppCommon_->GetCropedImage(); } - -void AclProcess::set_mode(bool flag) { repeat_ = flag; } - -bool AclProcess::get_mode() { return repeat_; } - -void AclProcess::device_memory_release() { dvppCommon_->ReleaseDvppBuffer(); } diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.h deleted file mode 100644 index c622546172..0000000000 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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. - */ - -#ifndef ACLMANAGER_H -#define ACLMANAGER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "acl/acl.h" -#include "CommonDataType.h" -#include "mindspore/core/utils/log_adapter.h" -#include "ErrorCode.h" -#include "DvppCommon.h" - -mode_t SetFileDefaultUmask(); - -class AclProcess { - public: - AclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight, aclrtContext context, - aclrtStream stream = nullptr, std::shared_ptr dvppCommon = nullptr); - - ~AclProcess() {} - - // Release all the resource - APP_ERROR Release(); - // Create resource for this sample - APP_ERROR InitResource(); - // Process the result - APP_ERROR Process(const RawData &ImageInfo); - // API for access memory - std::shared_ptr Get_Memory_Data(); - // API for access device memory - std::shared_ptr Get_Device_Memory_Data(); - // change output method - void set_mode(bool flag); - // Get the mode of Acl process - bool get_mode(); - // Crop definition - void CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo); - // D-chip memory release - void device_memory_release(); - - private: - // Initialize the modules used by this sample - APP_ERROR InitModule(); - // Preprocess the input image - APP_ERROR Preprocess(const RawData &ImageInfo); - - aclrtContext context_; - aclrtStream stream_; - std::shared_ptr dvppCommon_; // dvpp object - std::shared_ptr processedInfo_; // processed data - uint32_t resizeWidth_; // dvpp resize width - uint32_t resizeHeight_; // dvpp resize height - uint32_t cropWidth_; // dvpp crop width - uint32_t cropHeight_; // dvpp crop height - bool repeat_; // Repeatly process image or not -}; - -#endif diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CMakeLists.txt b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CMakeLists.txt index 2cd7ccce49..bdde6fa7b7 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CMakeLists.txt +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CMakeLists.txt @@ -4,7 +4,7 @@ set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE add_definitions(-DENABLE_DVPP_INTERFACE) add_library(dvpp-utils OBJECT - AclProcess.cc + MDAclProcess.cc DvppCommon.cc ErrorCode.cpp ResourceManager.cc diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h index b767606c95..cf898815a7 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "acl/acl.h" #include "acl/ops/acl_dvpp.h" @@ -42,15 +41,6 @@ const int JPEG_WIDTH_ALIGN = 128; const int JPEG_HEIGHT_ALIGN = 16; const int VPC_OFFSET_ALIGN = 2; -// Tensor Descriptor -struct Tensor { - aclDataType dataType; // Tensor data type - int numDim; // Number of dimensions of Tensor - std::vector dims; // Dimension vector - aclFormat format; // Format of tensor, e.g. ND, NCHW, NC1HWC0 - std::string name; // Name of tensor -}; - // Data type of tensor enum OpAttrType { BOOL = 0, @@ -92,8 +82,8 @@ struct ImageInfo { // Description of data in device struct RawData { - size_t lenOfByte; // Size of memory, bytes - std::shared_ptr data; // Smart pointer of data + size_t lenOfByte; // Size of memory, bytes + void *data; // Pointer of data }; // Description of data in device diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.cc index 33872ba8bf..9a93923c08 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.cc @@ -15,6 +15,7 @@ #include #include + #include "mindspore/core/utils/log_adapter.h" #include "DvppCommon.h" #include "CommonDataType.h" @@ -185,11 +186,16 @@ void DvppCommon::ReleaseDvppBuffer() { */ APP_ERROR DvppCommon::GetVpcDataSize(uint32_t width, uint32_t height, acldvppPixelFormat format, uint32_t &vpcSize) { // Check the invalid format of VPC function and calculate the output buffer size - if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420) { - MS_LOG(ERROR) << "Format[" << format << "] for VPC is not supported, just support NV12 or NV21."; + if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420 && + format != PIXEL_FORMAT_RGB_888) { + MS_LOG(ERROR) << "Format[" << format << "] for VPC is not supported, just support NV12 or NV21 or RGB888."; return APP_ERR_COMM_INVALID_PARAM; } uint32_t widthStride = DVPP_ALIGN_UP(width, VPC_WIDTH_ALIGN); + if (format == PIXEL_FORMAT_RGB_888) { + widthStride *= 3; + } + uint32_t heightStride = DVPP_ALIGN_UP(height, VPC_HEIGHT_ALIGN); vpcSize = widthStride * heightStride * YUV_BGR_SIZE_CONVERT_3 / YUV_BGR_SIZE_CONVERT_2; return APP_ERR_OK; @@ -254,12 +260,17 @@ APP_ERROR DvppCommon::GetVpcInputStrideSize(uint32_t width, uint32_t height, acl APP_ERROR DvppCommon::GetVpcOutputStrideSize(uint32_t width, uint32_t height, acldvppPixelFormat format, uint32_t &widthStride, uint32_t &heightStride) { // Check the invalidty of output format and calculate the output width and height - if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420) { - MS_LOG(ERROR) << "Output format[" << format << "] for VPC is not supported, just support NV12 or NV21."; + if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420 && + format != PIXEL_FORMAT_RGB_888) { + MS_LOG(ERROR) << "Output format[" << format << "] for VPC is not supported, just support NV12 or NV21 or RGB888."; return APP_ERR_COMM_INVALID_PARAM; } widthStride = DVPP_ALIGN_UP(width, VPC_STRIDE_WIDTH); + if (format == PIXEL_FORMAT_RGB_888) { + widthStride *= 3; + } + heightStride = DVPP_ALIGN_UP(height, VPC_STRIDE_HEIGHT); return APP_ERR_OK; } @@ -373,8 +384,9 @@ APP_ERROR DvppCommon::SetDvppPicDescData(const DvppDataInfo &dataInfo, acldvppPi * @return: APP_ERR_OK if success, other values if failure */ APP_ERROR DvppCommon::CheckResizeParams(const DvppDataInfo &input, const DvppDataInfo &output) { - if (output.format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && output.format != PIXEL_FORMAT_YVU_SEMIPLANAR_420) { - MS_LOG(ERROR) << "Output format[" << output.format << "] for VPC is not supported, just support NV12 or NV21."; + if (output.format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && output.format != PIXEL_FORMAT_YVU_SEMIPLANAR_420 && + output.format != PIXEL_FORMAT_RGB_888) { + MS_LOG(ERROR) << "Output format[" << output.format << "] for VPC is not supported, only NV12 or NV21 or RGB888."; return APP_ERR_COMM_INVALID_PARAM; } if (((float)output.height / input.height) < MIN_RESIZE_SCALE || @@ -419,6 +431,7 @@ APP_ERROR DvppCommon::ResizeProcess(acldvppPicDesc &inputDesc, acldvppPicDesc &o return ret; } } + return APP_ERR_OK; } @@ -770,6 +783,7 @@ APP_ERROR DvppCommon::CombineCropProcess(DvppCropInputInfo &input, DvppDataInfo if (ret != APP_ERR_OK) { return ret; } + // cropImage_所持有的成员变量 uint8_t *data通过acldvppMalloc()接口申请,位于Device上 cropImage_ = std::make_shared(); cropImage_->width = output.width; cropImage_->height = output.height; @@ -839,6 +853,44 @@ APP_ERROR DvppCommon::JpegDecode(DvppDataInfo &input, DvppDataInfo &output, bool return APP_ERR_OK; } +/* + * @description: Set the description of the output image and decode + * @param: input specifies the input image information + * @param: output specifies the output image information + * @param: withSynchronize specifies whether to execute synchronously + * @return: APP_ERR_OK if success, other values if failure + * @attention: This function can be called only when the DvppCommon object is initialized with Init + */ +APP_ERROR DvppCommon::PngDecode(DvppDataInfo &input, DvppDataInfo &output, bool withSynchronize) { + // Return special error code when the DvppCommon object is initialized with InitVdec + if (isVdec_) { + MS_LOG(ERROR) << "PngDecode cannot be called by the DvppCommon object which is initialized with InitVdec."; + return APP_ERR_DVPP_OBJ_FUNC_MISMATCH; + } + + acldvppPicDesc *outputDesc = acldvppCreatePicDesc(); + decodeOutputDesc_.reset(outputDesc, g_picDescDeleter); + + APP_ERROR ret = SetDvppPicDescData(output, *decodeOutputDesc_); + if (ret != APP_ERR_OK) { + return ret; + } + + ret = acldvppPngDecodeAsync(dvppChannelDesc_, input.data, input.dataSize, decodeOutputDesc_.get(), dvppStream_); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode png, ret = " << ret << "."; + return ret; + } + if (withSynchronize) { + ret = aclrtSynchronizeStream(dvppStream_); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to synchronize stream, ret = " << ret << "."; + return APP_ERR_DVPP_JPEG_DECODE_FAIL; + } + } + return APP_ERR_OK; +} + /* * @description: Get the aligned width and height of the image after decoding * @param: width specifies the width before alignment @@ -853,6 +905,17 @@ void DvppCommon::GetJpegDecodeStrideSize(uint32_t width, uint32_t height, uint32 heightStride = DVPP_ALIGN_UP(height, JPEGD_STRIDE_HEIGHT); } +void DvppCommon::GetPngDecodeStrideSize(uint32_t width, uint32_t height, uint32_t &widthStride, uint32_t &heightStride, + acldvppPixelFormat format) { + if (format == PIXEL_FORMAT_RGB_888) { + widthStride = DVPP_ALIGN_UP(width * 3, JPEGD_STRIDE_WIDTH); + heightStride = DVPP_ALIGN_UP(height, JPEGD_STRIDE_HEIGHT); + } else { + widthStride = DVPP_ALIGN_UP(width * 4, JPEGD_STRIDE_WIDTH); + heightStride = DVPP_ALIGN_UP(height, JPEGD_STRIDE_HEIGHT); + } +} + /* * @description: Get picture width and height and number of channels from image data * @param: data specifies the memory to store the image data @@ -886,6 +949,39 @@ APP_ERROR DvppCommon::GetJpegImageInfo(const void *data, uint32_t dataSize, uint return APP_ERR_OK; } +/* + * @description: Get picture width and height and number of channels from PNG image data + * @param: data specifies the memory to store the image data + * @param: dataSize specifies the size of the image data + * @param: width is used to save the image width + * @param: height is used to save the image height + * @param: components is used to save the number of channels + * @return: APP_ERR_OK if success, other values if failure + */ +APP_ERROR DvppCommon::GetPngImageInfo(const void *data, uint32_t dataSize, uint32_t &width, uint32_t &height, + int32_t &components) { + uint32_t widthTmp; + uint32_t heightTmp; + int32_t componentsTmp; + APP_ERROR ret = acldvppPngGetImageInfo(data, dataSize, &widthTmp, &heightTmp, &componentsTmp); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get image info of PNG, ret = " << ret << "."; + return ret; + } + if (widthTmp > MAX_PNGD_WIDTH || widthTmp < MIN_PNGD_WIDTH) { + MS_LOG(ERROR) << "Input width is invalid, not in [" << MIN_PNGD_WIDTH << ", " << MAX_PNGD_WIDTH << "]."; + return APP_ERR_COMM_INVALID_PARAM; + } + if (heightTmp > MAX_PNGD_HEIGHT || heightTmp < MIN_PNGD_HEIGHT) { + MS_LOG(ERROR) << "Input height is invalid, not in [" << MIN_PNGD_HEIGHT << ", " << MAX_PNGD_HEIGHT << "]."; + return APP_ERR_COMM_INVALID_PARAM; + } + width = widthTmp; + height = heightTmp; + components = componentsTmp; + return APP_ERR_OK; +} + /* * @description: Get the size of the buffer for storing decoded images based on the image data, size, and format * @param: data specifies the memory to store the image data @@ -906,6 +1002,26 @@ APP_ERROR DvppCommon::GetJpegDecodeDataSize(const void *data, uint32_t dataSize, return APP_ERR_OK; } +/* + * @description: Get the size of the buffer for storing decoded images based on the PNG image data, size, and format + * @param: data specifies the memory to store the image data + * @param: dataSize specifies the size of the image data + * @param: format specifies the image format + * @param: decSize is used to store the result size + * @return: APP_ERR_OK if success, other values if failure + */ +APP_ERROR DvppCommon::GetPngDecodeDataSize(const void *data, uint32_t dataSize, acldvppPixelFormat format, + uint32_t &decSize) { + uint32_t outputSize; + APP_ERROR ret = acldvppPngPredictDecSize(data, dataSize, format, &outputSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to predict decode size of png image, ret = " << ret << "."; + return ret; + } + decSize = outputSize; + return APP_ERR_OK; +} + /* * @description: Decode the image specified by imageInfo and save the result to member variable decodedImage_ * @param: imageInfo specifies image information @@ -923,24 +1039,27 @@ APP_ERROR DvppCommon::CombineJpegdProcess(const RawData &imageInfo, acldvppPixel } int32_t components; + // Member variable of inputImage_, uint8_t *data will be on device inputImage_ = std::make_shared(); inputImage_->format = format; APP_ERROR ret = - GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + // GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + GetJpegImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); if (ret != APP_ERR_OK) { MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << "."; return ret; } - // Get the buffer size of decode output according to the input data and output format + // Get the buffer size(On device) of decode output according to the input data and output format uint32_t outBuffSize; - ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize); + // ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize); + ret = GetJpegDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBuffSize); if (ret != APP_ERR_OK) { MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << "."; return ret; } - // In TransferImageH2D function, device buffer will be alloced to store the input image + // In TransferImageH2D function, device buffer will be alloced to store the input image before decode // Need to pay attention to release of the buffer ret = TransferImageH2D(imageInfo, inputImage_); if (ret != APP_ERR_OK) { @@ -976,6 +1095,150 @@ APP_ERROR DvppCommon::CombineJpegdProcess(const RawData &imageInfo, acldvppPixel return APP_ERR_OK; } +APP_ERROR DvppCommon::SinkCombineJpegdProcess(std::shared_ptr &input, + std::shared_ptr &output, bool withSynchronize) { + // Both input and output are locate on device, so we must release them if fail in decode + APP_ERROR ret = JpegDecode(*input, *output, withSynchronize); + if (ret != APP_ERR_OK) { + // Release the output buffer when decode failed, otherwise release it after use + RELEASE_DVPP_DATA(inputImage_->data); + inputImage_->data = nullptr; + RELEASE_DVPP_DATA(decodedImage_->data); + decodedImage_->data = nullptr; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR DvppCommon::SinkCombinePngdProcess(std::shared_ptr &input, + std::shared_ptr &output, bool withSynchronize) { + // Both input and output are locate on device, so we must release them if fail in decode + APP_ERROR ret = PngDecode(*input, *output, withSynchronize); + if (ret != APP_ERR_OK) { + // Release the output buffer when decode failed, otherwise release it after use + RELEASE_DVPP_DATA(inputImage_->data); + inputImage_->data = nullptr; + RELEASE_DVPP_DATA(decodedImage_->data); + decodedImage_->data = nullptr; + return ret; + } + return APP_ERR_OK; +} + +/* + * @description: Decode the image specified by imageInfo and save the result to member variable decodedImage_ + * This function is for PNG format image + * @param: imageInfo specifies image information + * @param: format specifies the image format + * @param: withSynchronize specifies whether to execute synchronously + * @return: APP_ERR_OK if success, other values if failure + * @attention: This function can be called only when the DvppCommon object is initialized with Init + */ +APP_ERROR DvppCommon::CombinePngdProcess(const RawData &imageInfo, acldvppPixelFormat format, bool withSynchronize) { + // Return special error code when the DvppCommon object is initialized with InitVdec + if (isVdec_) { + MS_LOG(ERROR) << "CombinePngdProcess cannot be called by the DvppCommon object which is initialized with InitVdec."; + return APP_ERR_DVPP_OBJ_FUNC_MISMATCH; + } + + int32_t components; + inputImage_ = std::make_shared(); + inputImage_->format = format; + APP_ERROR ret = + // GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + GetPngImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << "."; + return ret; + } + + // Get the buffer size of decode output according to the input data and output format + uint32_t outBuffSize; + // ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize); + ret = GetPngDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBuffSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << "."; + return ret; + } + + // In TransferImageH2D function, device buffer will be alloced to store the input image + // Need to pay attention to release of the buffer + ret = TransferImageH2D(imageInfo, inputImage_); + if (ret != APP_ERR_OK) { + return ret; + } + + decodedImage_ = std::make_shared(); + decodedImage_->format = format; + decodedImage_->width = inputImage_->width; + decodedImage_->height = inputImage_->height; + GetPngDecodeStrideSize(inputImage_->width, inputImage_->height, decodedImage_->widthStride, + decodedImage_->heightStride, format); + decodedImage_->dataSize = outBuffSize; + // Malloc dvpp buffer to store the output data after decoding + // Need to pay attention to release of the buffer + ret = acldvppMalloc((void **)&decodedImage_->data, decodedImage_->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to malloc memory on dvpp, ret = " << ret << "."; + RELEASE_DVPP_DATA(inputImage_->data); + return ret; + } + ret = PngDecode(*inputImage_, *decodedImage_, withSynchronize); + if (ret != APP_ERR_OK) { + // Release the output buffer when decode failed, otherwise release it after use + RELEASE_DVPP_DATA(inputImage_->data); + inputImage_->data = nullptr; + RELEASE_DVPP_DATA(decodedImage_->data); + decodedImage_->data = nullptr; + return ret; + } + + return APP_ERR_OK; +} + +/* + * @description: Transfer data from host to device + * @param: imageInfo specifies the image data on the host + * @return: APP_ERR_OK if success, other values if failure + */ +APP_ERROR DvppCommon::TransferYuvDataH2D(const DvppDataInfo &imageinfo) { + if (imageinfo.dataSize <= 0) { + MS_LOG(ERROR) << "The input buffer size on host should not be empty."; + return APP_ERR_COMM_INVALID_PARAM; + } + uint8_t *device_ptr = nullptr; + APP_ERROR ret = acldvppMalloc((void **)&device_ptr, imageinfo.dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to malloc " << imageinfo.dataSize << " bytes on dvpp, ret = " << ret << "."; + return ret; + } + ret = aclrtMemcpyAsync(device_ptr, imageinfo.dataSize, imageinfo.data, imageinfo.dataSize, ACL_MEMCPY_HOST_TO_DEVICE, + dvppStream_); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy " << imageinfo.dataSize << " bytes from host to device, ret = " << ret << "."; + RELEASE_DVPP_DATA(device_ptr); + return ret; + } + ret = aclrtSynchronizeStream(dvppStream_); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to synchronize stream, ret = " << ret << "."; + RELEASE_DVPP_DATA(device_ptr); + return ret; + } + /* Important!!! decodedImage_ speifies the image in deocded format(RGB OR YUV) + * Not essentailly to be the image after decode.(Specifies the data not in RAW encode format) + * It can also be the image after resize(Very important) + */ + decodedImage_ = std::make_shared(); + decodedImage_->data = device_ptr; + decodedImage_->dataSize = imageinfo.dataSize; + decodedImage_->height = imageinfo.height; + decodedImage_->heightStride = imageinfo.heightStride; + decodedImage_->width = imageinfo.width; + decodedImage_->widthStride = imageinfo.widthStride; + return APP_ERR_OK; +} + /* * @description: Transfer data from host to device * @param: imageInfo specifies the image data on the host @@ -983,7 +1246,13 @@ APP_ERROR DvppCommon::CombineJpegdProcess(const RawData &imageInfo, acldvppPixel * @return: APP_ERR_OK if success, other values if failure */ APP_ERROR DvppCommon::TransferImageH2D(const RawData &imageInfo, const std::shared_ptr &jpegInput) { - uint8_t *inDevBuff = nullptr; + // Check image buffer size validity + if (imageInfo.lenOfByte <= 0) { + MS_LOG(ERROR) << "The input buffer size on host should not be empty."; + return APP_ERR_COMM_INVALID_PARAM; + } + + uint8_t *inDevBuff = nullptr; // This pointer will be on device APP_ERROR ret = acldvppMalloc((void **)&inDevBuff, imageInfo.lenOfByte); if (ret != APP_ERR_OK) { MS_LOG(ERROR) << "Failed to malloc " << imageInfo.lenOfByte << " bytes on dvpp, ret = " << ret << "."; @@ -991,8 +1260,10 @@ APP_ERROR DvppCommon::TransferImageH2D(const RawData &imageInfo, const std::shar } // Copy the image data from host to device - ret = aclrtMemcpyAsync(inDevBuff, imageInfo.lenOfByte, imageInfo.data.get(), imageInfo.lenOfByte, - ACL_MEMCPY_HOST_TO_DEVICE, dvppStream_); + // ret = aclrtMemcpyAsync(inDevBuff, imageInfo.lenOfByte, imageInfo.data.get(), imageInfo.lenOfByte, + // ACL_MEMCPY_HOST_TO_DEVICE, dvppStream_); + ret = aclrtMemcpyAsync(inDevBuff, imageInfo.lenOfByte, imageInfo.data, imageInfo.lenOfByte, ACL_MEMCPY_HOST_TO_DEVICE, + dvppStream_); if (ret != APP_ERR_OK) { MS_LOG(ERROR) << "Failed to copy " << imageInfo.lenOfByte << " bytes from host to device, ret = " << ret << "."; RELEASE_DVPP_DATA(inDevBuff); @@ -1011,6 +1282,114 @@ APP_ERROR DvppCommon::TransferImageH2D(const RawData &imageInfo, const std::shar return APP_ERR_OK; } +/* + * Sink RawData(On host) into DvppDataInfo(On device) + */ +APP_ERROR DvppCommon::SinkImageH2D(const RawData &imageInfo, acldvppPixelFormat format) { + if (isVdec_) { + MS_LOG(ERROR) + << "CombineJpegdProcess cannot be called by the DvppCommon object which is initialized with InitVdec."; + return APP_ERR_DVPP_OBJ_FUNC_MISMATCH; + } + + int32_t components; + // Member variable of inputImage_, uint8_t *data will be on device + inputImage_ = std::make_shared(); + inputImage_->format = format; + APP_ERROR ret = + // GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + GetJpegImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << "."; + return ret; + } + + // Get the buffer size(On device) of decode output according to the input data and output format + uint32_t outBufferSize; + // ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize); + ret = GetJpegDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBufferSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << "."; + return ret; + } + // In TransferImageH2D function, device buffer will be alloced to store the input image before decode + // Need to pay attention to release of the buffer + ret = TransferImageH2D(imageInfo, inputImage_); + if (ret != APP_ERR_OK) { + return ret; + } + // This part is to define the data after decode (MALLOC ON DEVICE!!) + decodedImage_ = std::make_shared(); + decodedImage_->format = format; + decodedImage_->width = inputImage_->width; + decodedImage_->height = inputImage_->height; + GetJpegDecodeStrideSize(inputImage_->width, inputImage_->height, decodedImage_->widthStride, + decodedImage_->heightStride); + // Obtain all the attributes of inputImage_ + GetJpegDecodeStrideSize(inputImage_->width, inputImage_->height, inputImage_->widthStride, inputImage_->heightStride); + decodedImage_->dataSize = outBufferSize; + // Malloc dvpp buffer to store the output data after decoding + // Need to pay attention to release of the buffer + ret = acldvppMalloc((void **)&decodedImage_->data, decodedImage_->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to malloc memory on dvpp, ret = " << ret << "."; + RELEASE_DVPP_DATA(inputImage_->data); + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR DvppCommon::SinkImageH2D(const RawData &imageInfo) { + if (isVdec_) { + MS_LOG(ERROR) << "CombinePngdProcess cannot be called by the DvppCommon object which is initialized with InitVdec."; + return APP_ERR_DVPP_OBJ_FUNC_MISMATCH; + } + + int32_t components; + inputImage_ = std::make_shared(); + acldvppPixelFormat format = PIXEL_FORMAT_RGB_888; + inputImage_->format = format; + APP_ERROR ret = + GetPngImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << "."; + return ret; + } + + // Get the buffer size of decode output according to the input data and output format + uint32_t outBuffSize; + // ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize); + ret = GetPngDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBuffSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << "."; + return ret; + } + + // In TransferImageH2D function, device buffer will be alloced to store the input image + // Need to pay attention to release of the buffer + ret = TransferImageH2D(imageInfo, inputImage_); + if (ret != APP_ERR_OK) { + return ret; + } + + decodedImage_ = std::make_shared(); + decodedImage_->format = format; + decodedImage_->width = inputImage_->width; + decodedImage_->height = inputImage_->height; + GetPngDecodeStrideSize(inputImage_->width, inputImage_->height, decodedImage_->widthStride, + decodedImage_->heightStride, format); + decodedImage_->dataSize = outBuffSize; + // Malloc dvpp buffer to store the output data after decoding + // Need to pay attention to release of the buffer + ret = acldvppMalloc((void **)&decodedImage_->data, decodedImage_->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to malloc memory on dvpp, ret = " << ret << "."; + RELEASE_DVPP_DATA(inputImage_->data); + return ret; + } + return APP_ERR_OK; +} + /* * @description: Create and set the description of a video stream * @param: data specifies the information about the video stream diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h index 4499bf24e3..9ef95ab632 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h @@ -16,8 +16,6 @@ #ifndef DVPP_COMMON_H #define DVPP_COMMON_H -#include -#include #include "CommonDataType.h" #include "ErrorCode.h" #include "acl/ops/acl_dvpp.h" @@ -61,6 +59,8 @@ struct DeviceStreamData { const uint32_t JPEGD_STRIDE_WIDTH = 128; // Jpegd module output width need to align up to 128 const uint32_t JPEGD_STRIDE_HEIGHT = 16; // Jpegd module output height need to align up to 16 +const uint32_t PNGD_STRIDE_WIDTH = 128; // Pngd module output width need to align up to 128 +const uint32_t PNGD_STRIDE_HEIGHT = 16; // Pngd module output height need to align up to 16 const uint32_t JPEGE_STRIDE_WIDTH = 16; // Jpege module input width need to align up to 16 const uint32_t JPEGE_STRIDE_HEIGHT = 1; // Jpege module input height remains unchanged const uint32_t VPC_STRIDE_WIDTH = 16; // Vpc module output width need to align up to 16 @@ -77,6 +77,10 @@ const uint32_t MAX_JPEGD_WIDTH = 8192; // Max width of jpegd module const uint32_t MAX_JPEGD_HEIGHT = 8192; // Max height of jpegd module const uint32_t MIN_JPEGD_WIDTH = 32; // Min width of jpegd module const uint32_t MIN_JPEGD_HEIGHT = 32; // Min height of jpegd module +const uint32_t MAX_PNGD_WIDTH = 4096; // Max width of pngd module +const uint32_t MAX_PNGD_HEIGHT = 4096; // Max height of pngd module +const uint32_t MIN_PNGD_WIDTH = 32; // Min width of pngd module +const uint32_t MIN_PNGD_HEIGHT = 32; // Min height of pngd module const uint32_t MAX_JPEGE_WIDTH = 8192; // Max width of jpege module const uint32_t MAX_JPEGE_HEIGHT = 8192; // Max height of jpege module const uint32_t MIN_JPEGE_WIDTH = 32; // Min width of jpege module @@ -126,10 +130,16 @@ class DvppCommon { static APP_ERROR GetVpcOutputStrideSize(uint32_t width, uint32_t height, acldvppPixelFormat format, uint32_t &widthStride, uint32_t &heightStride); static void GetJpegDecodeStrideSize(uint32_t width, uint32_t height, uint32_t &widthStride, uint32_t &heightStride); + static void GetPngDecodeStrideSize(uint32_t width, uint32_t height, uint32_t &widthStride, uint32_t &heightStride, + acldvppPixelFormat format); static APP_ERROR GetJpegImageInfo(const void *data, uint32_t dataSize, uint32_t &width, uint32_t &height, int32_t &components); + static APP_ERROR GetPngImageInfo(const void *data, uint32_t dataSize, uint32_t &width, uint32_t &height, + int32_t &components); static APP_ERROR GetJpegDecodeDataSize(const void *data, uint32_t dataSize, acldvppPixelFormat format, uint32_t &decSize); + static APP_ERROR GetPngDecodeDataSize(const void *data, uint32_t dataSize, acldvppPixelFormat format, + uint32_t &decSize); static APP_ERROR GetJpegEncodeStrideSize(std::shared_ptr &input); static APP_ERROR SetEncodeLevel(uint32_t level, acldvppJpegeConfig &jpegeConfig); static APP_ERROR GetVideoDecodeStrideSize(uint32_t width, uint32_t height, acldvppPixelFormat format, @@ -143,6 +153,8 @@ class DvppCommon { APP_ERROR VpcCrop(const DvppCropInputInfo &input, const DvppDataInfo &output, bool withSynchronize); APP_ERROR JpegDecode(DvppDataInfo &input, DvppDataInfo &output, bool withSynchronize); + APP_ERROR PngDecode(DvppDataInfo &input, DvppDataInfo &output, bool withSynchronize); + APP_ERROR JpegEncode(DvppDataInfo &input, DvppDataInfo &output, acldvppJpegeConfig *jpegeConfig, bool withSynchronize); @@ -156,8 +168,17 @@ class DvppCommon { VpcProcessType processType = VPC_PT_DEFAULT); APP_ERROR CombineCropProcess(DvppCropInputInfo &input, DvppDataInfo &output, bool withSynchronize); APP_ERROR CombineJpegdProcess(const RawData &imageInfo, acldvppPixelFormat format, bool withSynchronize); + + APP_ERROR SinkCombineJpegdProcess(std::shared_ptr &input, std::shared_ptr &output, + bool withSynchronize); + APP_ERROR SinkCombinePngdProcess(std::shared_ptr &input, std::shared_ptr &output, + bool withSynchronize); + APP_ERROR CombineJpegeProcess(const RawData &imageInfo, uint32_t width, uint32_t height, acldvppPixelFormat format, bool withSynchronize); + // New feature for PNG format image decode + APP_ERROR CombinePngdProcess(const RawData &imageInfo, acldvppPixelFormat format, bool withSynchronize); + // The following interface can be called only when the DvppCommon object is initialized with InitVdec APP_ERROR CombineVdecProcess(std::shared_ptr data, void *userData); @@ -168,6 +189,15 @@ class DvppCommon { std::shared_ptr GetEncodedImage(); std::shared_ptr GetCropedImage(); + // Transfer DvppDataInfo from host to device, aim at resize and crop + APP_ERROR TransferYuvDataH2D(const DvppDataInfo &imageinfo); + // Transfer RawData(image) from host to device, aim at decode + APP_ERROR TransferImageH2D(const RawData &imageInfo, const std::shared_ptr &jpegInput); + // Transfer RawData(image on host) to inputImage_(data on device), this is for data sink mode + APP_ERROR SinkImageH2D(const RawData &imageInfo, acldvppPixelFormat format); + // This overload function is for PNG image sink, hence we ignore the pixel format + APP_ERROR SinkImageH2D(const RawData &imageInfo); + // Release the memory that is allocated in the interfaces which are started with "Combine" void ReleaseDvppBuffer(); APP_ERROR VdecSendEosFrame() const; @@ -185,7 +215,6 @@ class DvppCommon { bool withSynchronize); APP_ERROR CheckResizeParams(const DvppDataInfo &input, const DvppDataInfo &output); APP_ERROR CheckCropParams(const DvppCropInputInfo &input); - APP_ERROR TransferImageH2D(const RawData &imageInfo, const std::shared_ptr &jpegInput); APP_ERROR CreateStreamDesc(std::shared_ptr data); APP_ERROR DestroyResource(); diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.cpp b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.cpp index c223205a1c..d2e104d4dc 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.cpp +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.cpp @@ -37,13 +37,14 @@ std::string GetAppErrCodeInfo(const APP_ERROR err) { } } -void AssertErrorCode(const int code, const std::string &file, const std::string &function, const int line) { +void AssertErrorCode(const int code, const std::string file, const std::string function, const int line) { if (code != APP_ERR_OK) { MS_LOG(ERROR) << "Failed at " << file << "->" << function << "->" << line << ": error code=" << code; + exit(code); } } -void CheckErrorCode(const int code, const std::string &file, const std::string &function, const int line) { +void CheckErrorCode(const int code, const std::string file, const std::string function, const int line) { if (code != APP_ERR_OK) { MS_LOG(ERROR) << "Failed at " << file << "->" << function << "->" << line << ": error code=" << code; } diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h index 3a49fa30b4..b43bb950ae 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h @@ -139,7 +139,7 @@ enum { APP_ERROR_FACE_WEB_USE_PART_SUCCESS = APP_ERROR_FACE_WEB_USE_BASE + 4, // Web: partial search succeeded APP_ERROR_FACE_WEB_USE_NO_FACE = APP_ERROR_FACE_WEB_USE_BASE + 5, // Web: no face detected APP_ERR_QUEUE_END, // Not an error code, define the range of blocking queue - // error code + // error code }; const std::string APP_ERR_ACL_LOG_STRING[] = { [APP_ERR_OK] = "Success", @@ -249,10 +249,10 @@ const std::string APP_ERR_FACE_LOG_STRING[] = { }; std::string GetAppErrCodeInfo(APP_ERROR err); -void AssertErrorCode(const int code, const std::string &file, const std::string &function, const int line); -void CheckErrorCode(const int code, const std::string &file, const std::string &function, const int line); +void AssertErrorCode(const int code, const std::string file, const std::string function, const int line); +void CheckErrorCode(const int code, const std::string file, const std::string function, const int line); #define RtAssert(code) AssertErrorCode(code, __FILE__, __FUNCTION__, __LINE__); #define RtCheckError(code) CheckErrorCode(code, __FILE__, __FUNCTION__, __LINE__); -#endif // ERROR_CODE_H_ +#endif // ERROR_CODE_H_ \ No newline at end of file diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.cc new file mode 100644 index 0000000000..09d51fdb2c --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.cc @@ -0,0 +1,966 @@ +/* + * 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 "minddata/dataset/core/constants.h" +#include "minddata/dataset/core/tensor_shape.h" +#include "minddata/dataset/kernels/image/image_utils.h" +#include "MDAclProcess.h" +#include +#include +#include + +namespace { +const int BUFFER_SIZE = 2048; +const mode_t DEFAULT_FILE_PERMISSION = 0077; +} // namespace + +mode_t SetFileDefaultUmask() { return umask(DEFAULT_FILE_PERMISSION); } + +/* + * @description: Constructor + * @param: resizeWidth specifies the resized width + * @param: resizeHeight specifies the resized hegiht + * @param: stream is used to maintain the execution order of operations + * @param: context is used to manage the life cycle of objects + * @param: dvppCommon is a class for decoding and resizing + */ +MDAclProcess::MDAclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight, + aclrtContext context, bool is_crop, aclrtStream stream, + std::shared_ptr dvppCommon) + : resizeWidth_(resizeWidth), + resizeHeight_(resizeHeight), + cropWidth_(cropWidth), + cropHeight_(cropHeight), + context_(context), + stream_(stream), + contain_crop_(is_crop), + dvppCommon_(dvppCommon), + processedInfo_(nullptr) {} + +MDAclProcess::MDAclProcess(uint32_t ParaWidth, uint32_t ParaHeight, aclrtContext context, bool is_crop, + aclrtStream stream, std::shared_ptr dvppCommon) + : contain_crop_(is_crop), context_(context), stream_(stream), dvppCommon_(dvppCommon), processedInfo_(nullptr) { + if (is_crop) { + resizeWidth_ = 0; + resizeHeight_ = 0; + cropWidth_ = ParaWidth; + cropHeight_ = ParaHeight; + } else { + resizeWidth_ = ParaWidth; + resizeHeight_ = ParaHeight; + cropWidth_ = 0; + cropHeight_ = 0; + } +} + +MDAclProcess::MDAclProcess(aclrtContext context, bool is_crop, aclrtStream stream, + std::shared_ptr dvppCommon) + : resizeWidth_(0), + resizeHeight_(0), + cropWidth_(0), + cropHeight_(0), + contain_crop_(is_crop), + context_(context), + stream_(stream), + dvppCommon_(dvppCommon), + processedInfo_(nullptr) {} +/* + * @description: Release MDAclProcess resources + * @return: aclError which is error code of ACL API + */ +APP_ERROR MDAclProcess::Release() { + // Release objects resource + APP_ERROR ret = dvppCommon_->DeInit(); + dvppCommon_->ReleaseDvppBuffer(); + + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to deinitialize dvppCommon_, ret = " << ret; + return ret; + } + MS_LOG(INFO) << "dvppCommon_ object deinitialized successfully"; + dvppCommon_.reset(); + + // Release stream + if (stream_ != nullptr) { + ret = aclrtDestroyStream(stream_); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to destroy stream, ret = " << ret; + stream_ = nullptr; + return ret; + } + stream_ = nullptr; + } + MS_LOG(INFO) << "The stream is destroyed successfully"; + return APP_ERR_OK; +} + +/* + * @description: Initialize DvppCommon object + * @return: aclError which is error code of ACL API + */ +APP_ERROR MDAclProcess::InitModule() { + // Create Dvpp JpegD object + dvppCommon_ = std::make_shared(stream_); + if (dvppCommon_ == nullptr) { + MS_LOG(ERROR) << "Failed to create dvppCommon_ object"; + return APP_ERR_COMM_INIT_FAIL; + } + MS_LOG(INFO) << "DvppCommon object created successfully"; + APP_ERROR ret = dvppCommon_->Init(); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to initialize dvppCommon_ object, ret = " << ret; + return ret; + } + MS_LOG(INFO) << "DvppCommon object initialized successfully"; + return APP_ERR_OK; +} + +/* + * @description: Initialize MDAclProcess resources + * @return: aclError which is error code of ACL API + */ +APP_ERROR MDAclProcess::InitResource() { + APP_ERROR ret = aclrtSetCurrentContext(context_); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to get ACL context, ret = " << ret; + return ret; + } + MS_LOG(INFO) << "The context is created successfully"; + ret = aclrtCreateStream(&stream_); // Create stream for application + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to create ACL stream, ret = " << ret; + return ret; + } + MS_LOG(INFO) << "The stream is created successfully"; + // Initialize dvpp module + if (InitModule() != APP_ERR_OK) { + return APP_ERR_COMM_INIT_FAIL; + } + return APP_ERR_OK; +} + +std::shared_ptr MDAclProcess::GetDeviceModule() { return dvppCommon_; } + +/* + * Sink data from Tensor(On host) to DeviceTensor(On device) + * Two cases are different, jpeg and png + */ +APP_ERROR MDAclProcess::H2D_Sink(std::shared_ptr &input, + std::shared_ptr &device_input) { + RawData imageinfo; + uint32_t filesize = input->SizeInBytes(); + // MS_LOG(INFO) << "Filesize on host is: " << filesize; + imageinfo.lenOfByte = filesize; + unsigned char *buffer = const_cast(input->GetBuffer()); + imageinfo.data = static_cast(buffer); + // Transfer RawData(Raw image) from host to device, which we call sink + APP_ERROR ret; + if (IsNonEmptyJPEG(input)) { // case JPEG + ret = dvppCommon_->SinkImageH2D(imageinfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420); + } else { // case PNG + ret = dvppCommon_->SinkImageH2D(imageinfo); + } + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to transport Tensor to device, ret = " << ret; + return ret; + } + auto deviceInputData = dvppCommon_->GetInputImage(); + // std::cout << "[DEBUG]Sink data sunccessfully, Filesize on device is: " << deviceInputData->dataSize << std::endl; + const mindspore::dataset::DataType dvpp_data_type(mindspore::dataset::DataType::DE_UINT8); + const mindspore::dataset::TensorShape dvpp_shape({1, 1, 1}); + mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, &device_input); + device_input->SetAttributes(deviceInputData); + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::D2H_Pop(std::shared_ptr &device_output, + std::shared_ptr &output) { + void *resHostBuf = nullptr; + APP_ERROR ret = aclrtMallocHost(&resHostBuf, device_output->DeviceDataSize()); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), device_output->DeviceDataSize(), device_output->GetDeviceBuffer(), + device_output->DeviceDataSize(), ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + auto data = std::static_pointer_cast(processedInfo_); + unsigned char *ret_ptr = data.get(); + + mindspore::dataset::dsize_t dvppDataSize = device_output->DeviceDataSize(); + const mindspore::dataset::TensorShape dvpp_shape({dvppDataSize, 1, 1}); + uint32_t _output_width_ = device_output->GetYuvStrideShape()[0]; + uint32_t _output_widthStride_ = device_output->GetYuvStrideShape()[1]; + uint32_t _output_height_ = device_output->GetYuvStrideShape()[2]; + uint32_t _output_heightStride_ = device_output->GetYuvStrideShape()[3]; + const mindspore::dataset::DataType dvpp_data_type(mindspore::dataset::DataType::DE_UINT8); + mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, &output); + output->SetYuvShape(_output_width_, _output_widthStride_, _output_height_, _output_heightStride_); + if (!output->HasData()) { + return APP_ERR_COMM_ALLOC_MEM; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_D(const RawData &ImageInfo) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_D_(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp decode Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr DecodeOutData = dvppCommon_->GetDecodedImage(); + if (!DecodeOutData) { + MS_LOG(ERROR) << "Decode Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + + // Alloc host memory for the inference output according to the size of output + void *resHostBuf = nullptr; + ret = aclrtMallocHost(&resHostBuf, DecodeOutData->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), DecodeOutData->dataSize, DecodeOutData->data, DecodeOutData->dataSize, + ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_D() { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_D_(); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp decode Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr DecodeOutData = dvppCommon_->GetDecodedImage(); + if (!DecodeOutData) { + MS_LOG(ERROR) << "Decode Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_D_(const RawData &ImageInfo) { + APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_D_() { + auto input_ = dvppCommon_->GetInputImage(); + auto decode_output_ = dvppCommon_->GetDecodedImage(); + APP_ERROR ret = dvppCommon_->SinkCombineJpegdProcess(input_, decode_output_, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_R(const DvppDataInfo &ImageInfo) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_R_(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to resize, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp resize Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr ResizeOutData = dvppCommon_->GetResizedImage(); + if (!ResizeOutData) { + MS_LOG(ERROR) << "Resize Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + // Alloc host memory for the inference output according to the size of output + void *resHostBuf = nullptr; + ret = aclrtMallocHost(&resHostBuf, ResizeOutData->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), ResizeOutData->dataSize, ResizeOutData->data, ResizeOutData->dataSize, + ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_R(std::string &last_step) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_R_(last_step); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to resize, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp resize Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr ResizeOutData = dvppCommon_->GetResizedImage(); + if (!ResizeOutData) { + MS_LOG(ERROR) << "Resize Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_R_(const DvppDataInfo &ImageInfo) { + APP_ERROR ret = dvppCommon_->TransferYuvDataH2D(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy data from host to device, ret = " << ret << "."; + return ret; + } + std::shared_ptr decoded_image = dvppCommon_->GetDecodedImage(); + uint32_t pri_h = decoded_image->heightStride; + uint32_t pri_w = decoded_image->widthStride; + // Define the resize shape + DvppDataInfo resizeOut; + ResizeConfigFilter(resizeOut, pri_w, pri_h); + ret = dvppCommon_->CombineResizeProcess(*decoded_image, resizeOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_R_(std::string &last_step) { + std::shared_ptr input_image = std::make_shared(); + if (last_step == "Decode") { + input_image = dvppCommon_->GetDecodedImage(); + } else { + input_image = dvppCommon_->GetCropedImage(); + } + if (!input_image->data) { + MS_LOG(ERROR) << "Failed to get data for resize, please verify last step operation"; + return APP_ERR_DVPP_RESIZE_FAIL; + } + uint32_t pri_h = input_image->heightStride; + uint32_t pri_w = input_image->widthStride; + DvppDataInfo resizeOut; + ResizeConfigFilter(resizeOut, pri_w, pri_h); + APP_ERROR ret = dvppCommon_->CombineResizeProcess(*input_image, resizeOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_C(const DvppDataInfo &ImageInfo) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_C_(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to crop image, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp crop Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr CropOutData = dvppCommon_->GetCropedImage(); + if (!CropOutData) { + MS_LOG(ERROR) << "Crop Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + // Alloc host memory for the inference output according to the size of output + void *resHostBuf = nullptr; + ret = aclrtMallocHost(&resHostBuf, CropOutData->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), CropOutData->dataSize, CropOutData->data, CropOutData->dataSize, + ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_C(std::string &last_step) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_C_(last_step); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to crop image, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp crop Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr CropOutData = dvppCommon_->GetCropedImage(); + if (!CropOutData) { + MS_LOG(ERROR) << "Crop Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_C_(const DvppDataInfo &ImageInfo) { + APP_ERROR ret = dvppCommon_->TransferYuvDataH2D(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy data from host to device, ret = " << ret << "."; + return ret; + } + // Unneccessary to be image after resize, maybe after decode, we store both of them in DecodedImage() + std::shared_ptr resized_image = dvppCommon_->GetDecodedImage(); + uint32_t pri_h = resized_image->heightStride; + uint32_t pri_w = resized_image->widthStride; + // Validate the crop shape + DvppDataInfo cropOut; + cropOut.width = cropWidth_; + cropOut.height = cropHeight_; + if (cropOut.width > pri_w || cropOut.height > pri_h) { + MS_LOG(ERROR) << "Crop size can not excceed resize, please verify your input [CROP SIZE] parameters"; + return APP_ERR_COMM_INVALID_PARAM; + } + cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; + DvppCropInputInfo cropInfo; + cropInfo.dataInfo = *resized_image; + // Define crop area + CropRoiConfig cropCfg; + CropConfigFilter(cropCfg, cropInfo, *resized_image); + ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_C_(std::string &last_step) { + std::shared_ptr input_image = std::make_shared(); + if (last_step == "Resize") { + input_image = dvppCommon_->GetResizedImage(); + } else { + input_image = dvppCommon_->GetDecodedImage(); + } + if (!input_image->data) { + MS_LOG(ERROR) << "Failed to get input data for crop, please verify last step operation"; + return APP_ERR_DVPP_CROP_FAIL; + } + uint32_t pri_h = input_image->heightStride; + uint32_t pri_w = input_image->widthStride; + DvppDataInfo cropOut; + cropOut.width = cropWidth_; + cropOut.height = cropHeight_; + if (cropOut.width > pri_w || cropOut.height > pri_h) { + MS_LOG(ERROR) << "Crop size can not excceed resize, please verify your input [CROP SIZE] parameters"; + return APP_ERR_COMM_INVALID_PARAM; + } + cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; + DvppCropInputInfo cropInfo; + cropInfo.dataInfo = *input_image; + // Define crop area + CropRoiConfig cropCfg; + CropConfigFilter(cropCfg, cropInfo, *input_image); + APP_ERROR ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::PNG_D(const RawData &ImageInfo) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = PNG_D_(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr DecodeOutData = dvppCommon_->GetDecodedImage(); + if (!DecodeOutData) { + MS_LOG(ERROR) << "ResizedOutData returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + // Alloc host memory for the inference output according to the size of output + void *resHostBuf = nullptr; + ret = aclrtMallocHost(&resHostBuf, DecodeOutData->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), DecodeOutData->dataSize, DecodeOutData->data, DecodeOutData->dataSize, + ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::PNG_D() { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = PNG_D_(); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp decode Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr DecodeOutData = dvppCommon_->GetDecodedImage(); + if (!DecodeOutData) { + MS_LOG(ERROR) << "Decode Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::PNG_D_(const RawData &ImageInfo) { + APP_ERROR ret = dvppCommon_->CombinePngdProcess(ImageInfo, PIXEL_FORMAT_RGB_888, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::PNG_D_() { + auto input_ = dvppCommon_->GetInputImage(); + auto decode_output_ = dvppCommon_->GetDecodedImage(); + APP_ERROR ret = dvppCommon_->SinkCombinePngdProcess(input_, decode_output_, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +/* + * @description: Decode and scale the picture, and write the result to a file + * @param: imageFile specifies the image path to be processed + * @return: aclError which is error code of ACL API + */ +APP_ERROR MDAclProcess::JPEG_DRC(const RawData &ImageInfo) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_DRC_(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode or resize or crop, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + /* 测试Device内存 + */ + std::shared_ptr CropOutData = dvppCommon_->GetCropedImage(); + if (CropOutData->dataSize == 0) { + MS_LOG(ERROR) << "CropOutData return NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + // Alloc host memory for the inference output according to the size of output + void *resHostBuf = nullptr; + ret = aclrtMallocHost(&resHostBuf, CropOutData->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), CropOutData->dataSize, CropOutData->data, CropOutData->dataSize, + ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_DRC() { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_D_(); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode, ret = " << ret; + return ret; + } + std::string last_step = "Decode"; + ret = JPEG_R_(last_step); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to resize, ret = " << ret; + return ret; + } + last_step = "Resize"; + ret = JPEG_C_(last_step); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to crop, ret = " << ret; + return ret; + } + // Get output of crop module + std::shared_ptr CropOutData = dvppCommon_->GetCropedImage(); + if (!CropOutData) { + MS_LOG(ERROR) << "Decode Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp (Decode + Resize + Crop) Delay] cost: " << costMs << "ms\tfps: " << fps; + return APP_ERR_OK; +} + +/* + * @description: Read image files, and perform decoding and scaling + * @param: imageFile specifies the image path to be processed + * @return: aclError which is error code of ACL API + */ +APP_ERROR MDAclProcess::JPEG_DRC_(const RawData &ImageInfo) { + // Decode process + APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; + return ret; + } + // Get output of decoded jpeg image, decodeOutData locates on device + std::shared_ptr decodeOutData = dvppCommon_->GetDecodedImage(); + + if (decodeOutData == nullptr) { + MS_LOG(ERROR) << "Decode output buffer is null."; + return APP_ERR_COMM_INVALID_POINTER; + } + uint32_t pri_h = decodeOutData->heightStride; + uint32_t pri_w = decodeOutData->widthStride; + // Define output of resize jpeg image + DvppDataInfo resizeOut; + ResizeConfigFilter(resizeOut, pri_w, pri_h); + // Run resize application function + ret = dvppCommon_->CombineResizeProcess(*decodeOutData, resizeOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << "."; + return ret; + } + // Get output of resize jpeg image, resizeOutData locates on device + std::shared_ptr resizeOutData = dvppCommon_->GetResizedImage(); + if (resizeOutData == nullptr) { + MS_LOG(ERROR) << "resize output buffer is null."; + return APP_ERR_COMM_INVALID_POINTER; + } + // Define output of crop jpeg image + DvppDataInfo cropOut; + cropOut.width = cropWidth_; + cropOut.height = cropHeight_; + cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; + // Define input of crop jpeg image + DvppCropInputInfo cropInfo; + cropInfo.dataInfo = *resizeOutData; + // Define crop area + CropRoiConfig cropCfg; + CropConfigFilter(cropCfg, cropInfo, resizeOut); + ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_DR(const RawData &ImageInfo) { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_DR_(ImageInfo); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode or resize, ret = " << ret; + return ret; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps; + // Get output of resize module + std::shared_ptr ResizeOutData = dvppCommon_->GetResizedImage(); + if (!ResizeOutData) { + MS_LOG(ERROR) << "ResizedOutData returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + // Alloc host memory for the inference output according to the size of output + void *resHostBuf = nullptr; + ret = aclrtMallocHost(&resHostBuf, ResizeOutData->dataSize); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret; + return ret; + } + std::shared_ptr outBuf(resHostBuf, aclrtFreeHost); + processedInfo_ = outBuf; + // Memcpy the output data from device to host + ret = aclrtMemcpy(outBuf.get(), ResizeOutData->dataSize, ResizeOutData->data, ResizeOutData->dataSize, + ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_DR() { + struct timeval begin = {0}; + struct timeval end = {0}; + gettimeofday(&begin, nullptr); + // deal with image + APP_ERROR ret = JPEG_D_(); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to decode, ret = " << ret; + return ret; + } + std::string last_step = "Decode"; + ret = JPEG_R_(last_step); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to resize, ret = " << ret; + return ret; + } + // Get output of resize module + std::shared_ptr ResizeOutData = dvppCommon_->GetResizedImage(); + if (!ResizeOutData) { + MS_LOG(ERROR) << "Decode Data returns NULL"; + return APP_ERR_COMM_INVALID_POINTER; + } + gettimeofday(&end, nullptr); + // Calculate the time cost of preprocess + const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS; + const double fps = 1 * SEC2MS / costMs; + MS_LOG(INFO) << "[dvpp (Decode + Resize) Delay] cost: " << costMs << "ms\tfps: " << fps; + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::JPEG_DR_(const RawData &ImageInfo) { + // Decode process + APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << "."; + return ret; + } + // Get output of decoded jpeg image + std::shared_ptr decodeOutData = dvppCommon_->GetDecodedImage(); + if (decodeOutData == nullptr) { + MS_LOG(ERROR) << "Decode output buffer is null."; + return APP_ERR_COMM_INVALID_POINTER; + } + // Define output of resize jpeg image + uint32_t pri_h = decodeOutData->heightStride; + uint32_t pri_w = decodeOutData->widthStride; + DvppDataInfo resizeOut; + ResizeConfigFilter(resizeOut, pri_w, pri_h); + // Run resize application function + ret = dvppCommon_->CombineResizeProcess(*decodeOutData, resizeOut, true); + if (ret != APP_ERR_OK) { + MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +void MDAclProcess::CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo, DvppDataInfo &resizeinfo) { + if (resizeHeight_ != 0) { + cfg.up = (resizeHeight_ - cropHeight_) / 2; + if (cfg.up % 2 != 0) { + cfg.up++; + } + cfg.down = resizeHeight_ - (resizeHeight_ - cropHeight_) / 2; + if (cfg.down % 2 == 0) { + cfg.down--; + } + } else { + cfg.up = (resizeinfo.height - cropHeight_) / 2; + if (cfg.up % 2 != 0) { + cfg.up++; + } + cfg.down = resizeinfo.height - (resizeinfo.height - cropHeight_) / 2; + if (cfg.down % 2 == 0) { + cfg.down--; + } + } + if (resizeWidth_ != 0) { + cfg.left = (resizeWidth_ - cropWidth_) / 2; + if (cfg.left % 2 != 0) { + cfg.left++; + } + cfg.right = resizeWidth_ - (resizeWidth_ - cropWidth_) / 2; + if (cfg.right % 2 == 0) { + cfg.right--; + } + } else { + cfg.left = (resizeinfo.width - cropWidth_) / 2; + if (cfg.left % 2 != 0) { + cfg.left++; + } + cfg.right = resizeinfo.width - (resizeinfo.width - cropWidth_) / 2; + if (cfg.right % 2 == 0) { + cfg.right--; + } + } + cropinfo.roi = cfg; +} + +APP_ERROR MDAclProcess::ResizeConfigFilter(DvppDataInfo &resizeinfo, const uint32_t pri_w_, const uint32_t pri_h_) { + if (resizeWidth_ != 0) { // 如果输入参数个数为2,按指定参数缩放 + resizeinfo.width = resizeWidth_; + resizeinfo.widthStride = DVPP_ALIGN_UP(resizeWidth_, VPC_STRIDE_WIDTH); + resizeinfo.height = resizeHeight_; + resizeinfo.heightStride = DVPP_ALIGN_UP(resizeHeight_, VPC_STRIDE_HEIGHT); + } else { // 如果输入参数个数为1,保持原图片比例缩放 + if (pri_h_ >= pri_w_) { + resizeinfo.width = resizeHeight_; // 若输入参数个数为1,则只有resizeHeight_有值 + resizeinfo.widthStride = DVPP_ALIGN_UP(resizeinfo.width, VPC_STRIDE_WIDTH); + resizeinfo.height = uint32_t(resizeHeight_ * pri_h_ / pri_w_); + resizeinfo.heightStride = DVPP_ALIGN_UP(resizeinfo.height, VPC_STRIDE_HEIGHT); + } else { + resizeinfo.width = uint32_t(resizeHeight_ * pri_w_ / pri_h_); + resizeinfo.widthStride = DVPP_ALIGN_UP(resizeinfo.width, VPC_STRIDE_WIDTH); + resizeinfo.height = resizeHeight_; + resizeinfo.heightStride = DVPP_ALIGN_UP(resizeinfo.height, VPC_STRIDE_HEIGHT); + } + } + resizeinfo.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; + return APP_ERR_OK; +} +/* + * @description: Obtain result data of memory + * @param: processed_data is result data info pointer + * @return: Address of data in the memory + */ +std::shared_ptr MDAclProcess::Get_Memory_Data() { return processedInfo_; } + +std::shared_ptr MDAclProcess::Get_Croped_DeviceData() { return dvppCommon_->GetCropedImage(); } + +std::shared_ptr MDAclProcess::Get_Resized_DeviceData() { return dvppCommon_->GetResizedImage(); } + +std::shared_ptr MDAclProcess::Get_Decode_DeviceData() { return dvppCommon_->GetDecodedImage(); } + +APP_ERROR MDAclProcess::SetResizeParas(uint32_t width, uint32_t height) { + resizeWidth_ = width; + resizeHeight_ = height; + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::SetCropParas(uint32_t width, uint32_t height) { + cropWidth_ = width; + cropHeight_ = height; + return APP_ERR_OK; +} + +APP_ERROR MDAclProcess::device_memory_release() { + dvppCommon_->ReleaseDvppBuffer(); + MS_LOG(INFO) << "Device memory release successfully"; + return APP_ERR_OK; +} + +std::vector MDAclProcess::Get_Primary_Shape() { + std::vector pri_shape; + if (!dvppCommon_) { + pri_shape.emplace_back(dvppCommon_->GetDecodedImage()->heightStride); + pri_shape.emplace_back(dvppCommon_->GetDecodedImage()->widthStride); + } + return pri_shape; +} diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h new file mode 100644 index 0000000000..3e875a9601 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#ifndef MDACLMANAGER_H +#define MDACLMANAGER_H + +#include +#include +#include +#include +#include +#include +#include "acl/acl.h" +#include "CommonDataType.h" +#include "minddata/dataset/core/tensor_shape.h" +#include "minddata/dataset/core/data_type.h" +#include "mindspore/ccsrc/minddata/dataset/core/device_tensor.h" +#include "mindspore/ccsrc/minddata/dataset/core/tensor.h" +#include "mindspore/core/utils/log_adapter.h" +#include "mindspore/ccsrc/minddata/dataset/util/status.h" +#include "ErrorCode.h" +#include "DvppCommon.h" +#include +#include +#include +#include + +mode_t SetFileDefaultUmask(); + +class MDAclProcess { + public: + MDAclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight, + aclrtContext context, bool is_crop = true, aclrtStream stream = nullptr, + std::shared_ptr dvppCommon = nullptr); + + MDAclProcess(uint32_t ParaWidth, uint32_t ParaHeight, aclrtContext context, bool is_crop = false, + aclrtStream stream = nullptr, std::shared_ptr dvppCommon = nullptr); + + MDAclProcess(aclrtContext context, bool is_crop = false, aclrtStream stream = nullptr, + std::shared_ptr dvppCommon = nullptr); + + ~MDAclProcess(){}; + + // Release all the resource + APP_ERROR Release(); + // Create resource for this sample + APP_ERROR InitResource(); + // Process the result + APP_ERROR JPEG_DRC(const RawData &ImageInfo); + APP_ERROR JPEG_DRC(); + // Procss the image without crop + APP_ERROR JPEG_DR(const RawData &ImageInfo); + APP_ERROR JPEG_DR(); + // Process the JPEG image only with decode + APP_ERROR JPEG_D(const RawData &ImageInfo); + APP_ERROR JPEG_D(); + // Process the JPEG image only with resize + APP_ERROR JPEG_R(const DvppDataInfo &ImageInfo); + APP_ERROR JPEG_R(std::string &last_step); + // Process the JPEG image only with crop + APP_ERROR JPEG_C(const DvppDataInfo &ImageInfo); + APP_ERROR JPEG_C(std::string &last_step); + // Process the PNG image only with decode + APP_ERROR PNG_D(const RawData &ImageInfo); + APP_ERROR PNG_D(); + // API for access memory + std::shared_ptr Get_Memory_Data(); + // API for access device memory of croped data + std::shared_ptr Get_Croped_DeviceData(); + // API for access device memory of resized data + std::shared_ptr Get_Resized_DeviceData(); + // API for access device memory of decode data + std::shared_ptr Get_Decode_DeviceData(); + + APP_ERROR H2D_Sink(std::shared_ptr &input, + std::shared_ptr &device_input); + + APP_ERROR D2H_Pop(std::shared_ptr &device_output, + std::shared_ptr &output); + + // D-chip memory release + APP_ERROR device_memory_release(); + + std::shared_ptr GetDeviceModule(); + + std::vector Get_Primary_Shape(); + + // Set Dvpp parameters + APP_ERROR SetResizeParas(uint32_t width, uint32_t height); + APP_ERROR SetCropParas(uint32_t width, uint32_t height); + + private: + // Crop definition + void CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo, DvppDataInfo &resizeinfo); + // Resize definition + APP_ERROR ResizeConfigFilter(DvppDataInfo &resizeinfo, const uint32_t pri_w_, const uint32_t pri_h_); + // Initialize DVPP modules used by this sample + APP_ERROR InitModule(); + // Dvpp process with crop + APP_ERROR JPEG_DRC_(const RawData &ImageInfo); + // Dvpp process without crop + APP_ERROR JPEG_DR_(const RawData &ImageInfo); + // Impl of JPEG_D + APP_ERROR JPEG_D_(const RawData &ImageInfo); + APP_ERROR JPEG_D_(); + // Impl of JPEG_R + APP_ERROR JPEG_R_(const DvppDataInfo &ImageInfo); + APP_ERROR JPEG_R_(std::string &last_step); + // Impl of JPEG_C + APP_ERROR JPEG_C_(const DvppDataInfo &ImageInfo); + APP_ERROR JPEG_C_(std::string &last_step); + // Impl of PNG_D + APP_ERROR PNG_D_(const RawData &ImageInfo); + APP_ERROR PNG_D_(); + + aclrtContext context_; + aclrtStream stream_; + std::shared_ptr dvppCommon_; // dvpp object + std::shared_ptr processedInfo_; // processed data (On host) + uint32_t resizeWidth_; // dvpp resize width + uint32_t resizeHeight_; // dvpp resize height + uint32_t cropWidth_; // dvpp crop width + uint32_t cropHeight_; // dvpp crop height + bool contain_crop_; // Initialize with crop or not +}; + +#endif diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.cc index 4ac49c4728..9dc3a28f8e 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.cc @@ -29,15 +29,15 @@ std::shared_ptr ResourceManager::ptr_ = nullptr; */ APP_ERROR ExistFile(const std::string &filePath) { struct stat fileSat = {0}; - char c[PATH_MAX_ASCEND + 1] = {0x00}; - size_t count = filePath.copy(c, PATH_MAX_ASCEND + 1); + char c[PATH_MAX + 1] = {0x00}; + size_t count = filePath.copy(c, PATH_MAX + 1); if (count != filePath.length()) { MS_LOG(ERROR) << "Failed to strcpy" << c; return APP_ERR_COMM_FAILURE; } // Get the absolute path of input directory - char path[PATH_MAX_ASCEND + 1] = {0x00}; - if ((strlen(c) > PATH_MAX_ASCEND) || (realpath(c, path) == nullptr)) { + char path[PATH_MAX + 1] = {0x00}; + if ((strlen(c) > PATH_MAX) || (realpath(c, path) == nullptr)) { MS_LOG(ERROR) << "Failed to get canonicalize path"; return APP_ERR_COMM_EXIST; } @@ -85,7 +85,6 @@ APP_ERROR ResourceManager::InitResource(ResourceInfo &resourceInfo) { MS_LOG(INFO) << "Acl has been initialized, skip."; return APP_ERR_OK; } - std::string &aclConfigPath = resourceInfo.aclConfigPath; APP_ERROR ret; if (aclConfigPath.length() == 0) { diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h index d27b9611d2..adfbb58b2a 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h @@ -16,20 +16,18 @@ #ifndef RESOURCEMANAGER_H #define RESOURCEMANAGER_H -#include #include #include #include -#include #include -#include #include #include "CommonDataType.h" #include "ErrorCode.h" +#include #include "mindspore/core/utils/log_adapter.h" #include "mindspore/ccsrc/cxx_api/graph/acl/acl_env_guard.h" -#define PATH_MAX_ASCEND 4096 +#define PATH_MAX 4096 enum ModelLoadMethod { LOAD_FROM_FILE = 0, // Loading from file, memory of model and weights are managed by ACL @@ -63,10 +61,12 @@ struct ResourceInfo { APP_ERROR ExistFile(const std::string &filePath); class ResourceManager { + friend APP_ERROR ExistFile(const std::string &filePath); + public: - ResourceManager() {} + ResourceManager(){}; - ~ResourceManager() {} + ~ResourceManager(){}; // Get the Instance of resource manager static std::shared_ptr GetInstance(); @@ -89,4 +89,4 @@ class ResourceManager { std::shared_ptr acl_env_; }; -#endif +#endif \ No newline at end of file diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc index c61e8f3f3c..5984d02edf 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc @@ -142,6 +142,12 @@ bool IsNonEmptyJPEG(const std::shared_ptr &input) { return input->SizeInBytes() > kJpegMagicLen && memcmp(input->GetBuffer(), kJpegMagic, kJpegMagicLen) == 0; } +bool IsNonEmptyPNG(const std::shared_ptr &input) { + const unsigned char *kPngMagic = (unsigned char *)"\x89\x50\x4E\x47"; + constexpr size_t kPngMagicLen = 4; + return input->SizeInBytes() > kPngMagicLen && memcmp(input->GetBuffer(), kPngMagic, kPngMagicLen) == 0; +} + Status Decode(const std::shared_ptr &input, std::shared_ptr *output) { if (IsNonEmptyJPEG(input)) { return JpegCropAndDecode(input, output); @@ -953,7 +959,7 @@ Status Erase(const std::shared_ptr &input, std::shared_ptr *outp RETURN_STATUS_UNEXPECTED("CutOut: load image failed."); } if (input_cv->Rank() != 3 || num_channels != 3) { - RETURN_STATUS_UNEXPECTED("CutOut: image shape is not ."); + RETURN_STATUS_UNEXPECTED("CutOut: image shape is not or ."); } cv::Mat input_img = input_cv->mat(); int32_t image_h = input_cv->shape()[0]; diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h index 9f34fc8005..dab2234587 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h @@ -103,6 +103,8 @@ Status DecodeCv(const std::shared_ptr &input, std::shared_ptr *o bool IsNonEmptyJPEG(const std::shared_ptr &input); +bool IsNonEmptyPNG(const std::shared_ptr &input); + void JpegSetSource(j_decompress_ptr c_info, const void *data, int64_t data_size); Status JpegCropAndDecode(const std::shared_ptr &input, std::shared_ptr *output, int x = 0, int y = 0, diff --git a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc index 8e563b7e70..87d49cc32d 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc @@ -32,9 +32,6 @@ #include "minddata/dataset/kernels/image/cut_out_op.h" #endif #include "minddata/dataset/kernels/image/decode_op.h" -#ifdef ENABLE_ACL -#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h" -#endif #ifndef ENABLE_ANDROID #include "minddata/dataset/kernels/image/equalize_op.h" #include "minddata/dataset/kernels/image/hwc_to_chw_op.h" @@ -305,102 +302,6 @@ Status MixUpBatchOperation::to_json(nlohmann::json *out_json) { #endif -#ifdef ENABLE_ACL -// DvppDecodeResizeCropOperation -DvppDecodeResizeCropOperation::DvppDecodeResizeCropOperation(const std::vector &crop, - const std::vector &resize) - : crop_(crop), resize_(resize) {} - -Status DvppDecodeResizeCropOperation::ValidateParams() { - // size - if (crop_.empty() || crop_.size() > 2) { - std::string err_msg = "DvppDecodeResizeCropJpeg: crop resolution must be a vector of one or two elements, got: " + - std::to_string(crop_.size()); - MS_LOG(ERROR) << err_msg; - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - if (resize_.empty() || resize_.size() > 2) { - std::string err_msg = "DvppDecodeResizeCropJpeg: resize resolution must be a vector of one or two elements, got: " + - std::to_string(resize_.size()); - MS_LOG(ERROR) << err_msg; - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) { - std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got Crop Parameters: "; - if (crop_.size() == 2) { - MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]"; - } else { - MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]"; - } - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) { - std::string err_msg = - "Dvpp module supports resize image with resolution in range [32, 2048], got Crop Parameters: "; - if (resize_.size() == 2) { - MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]"; - } else { - MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]"; - } - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - if (crop_.size() < resize_.size()) { - if (crop_[0] > MIN(resize_[0], resize_[1])) { - std::string err_msg = - "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= " - "y[0], and x[1] <= y[1], please verify your input parameters."; - MS_LOG(ERROR) << err_msg; - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - } - if (crop_.size() > resize_.size()) { - if (MAX(crop_[0], crop_[1]) > resize_[0]) { - std::string err_msg = - "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= " - "y[0], and x[1] <= y[1], please verify your input parameters."; - MS_LOG(ERROR) << err_msg; - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - } - if (crop_.size() == resize_.size()) { - for (int32_t i = 0; i < crop_.size(); ++i) { - if (crop_[i] > resize_[i]) { - std::string err_msg = - "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= " - "y[0], and x[1] <= y[1], please verify your input parameters."; - MS_LOG(ERROR) << err_msg; - RETURN_STATUS_SYNTAX_ERROR(err_msg); - } - } - } - return Status::OK(); -} - -std::shared_ptr DvppDecodeResizeCropOperation::Build() { - // If size is a single value, the smaller edge of the image will be - // resized to this value with the same image aspect ratio. - uint32_t cropHeight, cropWidth, resizeHeight, resizeWidth; - if (crop_.size() == 1) { - cropHeight = crop_[0]; - cropWidth = crop_[0]; - } else { - cropHeight = crop_[0]; - cropWidth = crop_[1]; - } - // User specified the width value. - if (resize_.size() == 1) { - resizeHeight = resize_[0]; - resizeWidth = resize_[0]; - } else { - resizeHeight = resize_[0]; - resizeWidth = resize_[1]; - } - std::shared_ptr tensor_op = - std::make_shared(cropHeight, cropWidth, resizeHeight, resizeWidth); - return tensor_op; -} -#endif - // NormalizeOperation NormalizeOperation::NormalizeOperation(std::vector mean, std::vector std) : mean_(mean), std_(std) {} diff --git a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h index 5c4088c47f..267d93afec 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h @@ -42,7 +42,6 @@ constexpr char kCropOperation[] = "Crop"; constexpr char kCutMixBatchOperation[] = "CutMixBatch"; constexpr char kCutOutOperation[] = "CutOut"; constexpr char kDecodeOperation[] = "Decode"; -constexpr char kDvppDecodeResizeCropOperation[] = "DvppDecodeResizeCrop"; constexpr char kEqualizeOperation[] = "Equalize"; constexpr char kHwcToChwOperation[] = "HwcToChw"; constexpr char kInvertOperation[] = "Invert"; @@ -88,7 +87,6 @@ class CropOperation; class CutMixBatchOperation; class CutOutOperation; class DecodeOperation; -class DvppDecodeResizeCropOperation; class EqualizeOperation; class HwcToChwOperation; class InvertOperation; @@ -258,23 +256,6 @@ class DecodeOperation : public TensorOperation { bool rgb_; }; -class DvppDecodeResizeCropOperation : public TensorOperation { - public: - explicit DvppDecodeResizeCropOperation(const std::vector &crop, const std::vector &resize); - - ~DvppDecodeResizeCropOperation() = default; - - std::shared_ptr Build() override; - - Status ValidateParams() override; - - std::string Name() const override { return kDvppDecodeResizeCropOperation; } - - private: - std::vector crop_; - std::vector resize_; -}; - class EqualizeOperation : public TensorOperation { public: ~EqualizeOperation() = default; diff --git a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.cc index 974de7f3ab..bec8049a67 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.cc @@ -48,6 +48,13 @@ Status TensorOp::Compute(const TensorRow &input, TensorRow *output) { "Is this TensorOp oneToOne? If no, please implement this Compute() in the derived class."); } +Status TensorOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + return Status(StatusCode::kMDUnexpectedError, + "Wrong Compute() function is called. This is a function for operators which can be executed by" + "different device. If so, please implement it in the derived class."); +} + Status TensorOp::OutputShape(const std::vector &inputs, std::vector &outputs) { if (inputs.size() != NumInput()) return Status(StatusCode::kMDUnexpectedError, @@ -63,5 +70,11 @@ Status TensorOp::OutputType(const std::vector &inputs, std::vector &processor) { + return Status(StatusCode::kMDUnexpectedError, + "This is a CPU operator which doesn't have Ascend Resource. Please verify your context"); +} +#endif } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h index 4d9149fc2d..78765a8fb9 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h @@ -24,6 +24,10 @@ #include "minddata/dataset/core/tensor.h" #include "minddata/dataset/core/tensor_row.h" #include "minddata/dataset/util/status.h" +#include "minddata/dataset/core/device_tensor.h" +#ifdef ENABLE_ACL +#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h" +#endif #define IO_CHECK(input, output) \ do { \ @@ -58,7 +62,12 @@ constexpr char kCenterCropOp[] = "CenterCropOp"; constexpr char kCutMixBatchOp[] = "CutMixBatchOp"; constexpr char kCutOutOp[] = "CutOutOp"; constexpr char kCropOp[] = "CropOp"; +constexpr char kDvppCropJpegOp[] = "DvppCropJpegOp"; constexpr char kDvppDecodeResizeCropJpegOp[] = "DvppDecodeResizeCropJpegOp"; +constexpr char kDvppDecodeResizeJpegOp[] = "DvppDecodeResizeJpegOp"; +constexpr char kDvppDecodeJpegOp[] = "DvppDecodeJpegOp"; +constexpr char kDvppDecodePngOp[] = "DvppDecodePngOp"; +constexpr char kDvppResizeJpegOp[] = "DvppResizeJpegOp"; constexpr char kEqualizeOp[] = "EqualizeOp"; constexpr char kHwcToChwOp[] = "HWC2CHWOp"; constexpr char kInvertOp[] = "InvertOp"; @@ -168,6 +177,12 @@ class TensorOp { // @return Status virtual Status Compute(const TensorRow &input, TensorRow *output); + // Perform an operation on one DeviceTensor and produce one DeviceTensor. This is for 1-to-1 column MapOp + // @param input shares the ownership of the Tensor (increase the ref count). + // @param output the address to a shared_ptr where the result will be placed. + // @return Status + virtual Status Compute(const std::shared_ptr &input, std::shared_ptr *output); + // Returns true oif the TensorOp takes one input and returns one output. // @return true/false bool OneToOne() { return NumInput() == 1 && NumOutput() == 1; } @@ -201,6 +216,9 @@ class TensorOp { virtual std::string Name() const = 0; virtual Status to_json(nlohmann::json *out_json) { return Status::OK(); } +#ifdef ENABLE_ACL + virtual Status SetAscendResource(const std::shared_ptr &processor); +#endif protected: bool is_deterministic_{true}; diff --git a/tests/st/cpp/CMakeLists.txt b/tests/st/cpp/CMakeLists.txt index a4abc71f61..e92887e4c2 100644 --- a/tests/st/cpp/CMakeLists.txt +++ b/tests/st/cpp/CMakeLists.txt @@ -7,6 +7,9 @@ include_directories(${CMAKE_SOURCE_DIR}/mindspore/core) include_directories(${CMAKE_BINARY_DIR}) include_directories(${CUDA_INCLUDE_DIRS}) +if(ENABLE_ACL) + add_definitions(-D ENABLE_ACL) +endif() file(GLOB_RECURSE CXX_ST_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cc) add_executable(st_tests ${CXX_ST_SRC}) target_link_libraries(st_tests PRIVATE mindspore_shared_lib _c_dataengine mindspore::gtest) diff --git a/tests/st/cpp/dataset/test_de.cc b/tests/st/cpp/dataset/test_de.cc index 3077b98fe0..02cb4e7818 100644 --- a/tests/st/cpp/dataset/test_de.cc +++ b/tests/st/cpp/dataset/test_de.cc @@ -19,6 +19,9 @@ #include "include/api/types.h" #include "minddata/dataset/include/execute.h" #include "minddata/dataset/include/vision.h" +#ifdef ENABLE_ACL +#include "minddata/dataset/include/vision_ascend.h" +#endif #include "minddata/dataset/kernels/tensor_op.h" #include "include/api/model.h" #include "include/api/serialization.h" @@ -39,10 +42,9 @@ TEST_F(TestDE, TestResNetPreprocess) { auto image = mindspore::MSTensor(std::make_shared(de_tensor)); // Define transform operations - mindspore::dataset::Execute Transform({ - Decode(), Resize({224, 224}), - Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}), - HWC2CHW()}); + mindspore::dataset::Execute Transform( + {Decode(), Resize({224, 224}), + Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}), HWC2CHW()}); // Apply transform on images Status rc = Transform(image, &image); @@ -63,9 +65,9 @@ TEST_F(TestDE, TestDvpp) { auto image = MSTensor(std::make_shared(de_tensor)); // Define dvpp transform - std::vector crop_size = {224, 224}; - std::vector resize_size = {256, 256}; - mindspore::dataset::Execute Transform(DvppDecodeResizeCropJpeg(crop_size, resize_size)); + std::vector crop_paras = {224, 224}; + std::vector resize_paras = {256, 256}; + mindspore::dataset::Execute Transform(DvppDecodeResizeCropJpeg(crop_paras, resize_paras)); // Apply transform on images Status rc = Transform(image, &image); @@ -75,16 +77,52 @@ TEST_F(TestDE, TestDvpp) { ASSERT_EQ(image.Shape().size(), 3); int32_t real_h = 0; int32_t real_w = 0; - int32_t remainder = crop_size[crop_size.size() - 1] % 16; - if (crop_size.size() == 1) { - real_h = (crop_size[0] % 2 == 0) ? crop_size[0] : crop_size[0] + 1; - real_w = (remainder == 0) ? crop_size[0] : crop_size[0] + 16 - remainder; + int32_t remainder = crop_paras[crop_paras.size() - 1] % 16; + if (crop_paras.size() == 1) { + real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1; + real_w = (remainder == 0) ? crop_paras[0] : crop_paras[0] + 16 - remainder; } else { - real_h = (crop_size[0] % 2 == 0) ? crop_size[0] : crop_size[0] + 1; - real_w = (remainder == 0) ? crop_size[1] : crop_size[1] + 16 - remainder; + real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1; + real_w = (remainder == 0) ? crop_paras[1] : crop_paras[1] + 16 - remainder; } ASSERT_EQ(image.Shape()[0], real_h * real_w * 1.5); // For image in YUV format, each pixel takes 1.5 byte ASSERT_EQ(image.Shape()[1], 1); ASSERT_EQ(image.Shape()[2], 1); #endif } + +TEST_F(TestDE, TestDvppSinkMode) { +#ifdef ENABLE_ACL + // Read images from target directory + std::shared_ptr de_tensor; + mindspore::dataset::Tensor::CreateFromFile("./data/dataset/apple.jpg", &de_tensor); + auto image = MSTensor(std::make_shared(de_tensor)); + + // Define dvpp transform + std::vector crop_paras = {224, 224}; + std::vector resize_paras = {256}; + mindspore::dataset::Execute Transform({DvppDecodeJpeg(), DvppResizeJpeg(resize_paras), DvppCropJpeg(crop_paras)}, + "Ascend310"); + + // Apply transform on images + Status rc = Transform(image, &image); + + // Check image info + ASSERT_TRUE(rc.IsOk()); + ASSERT_EQ(image.Shape().size(), 2); + int32_t real_h = 0; + int32_t real_w = 0; + int32_t remainder = crop_paras[crop_paras.size() - 1] % 16; + if (crop_paras.size() == 1) { + real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1; + real_w = (remainder == 0) ? crop_paras[0] : crop_paras[0] + 16 - remainder; + } else { + real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1; + real_w = (remainder == 0) ? crop_paras[1] : crop_paras[1] + 16 - remainder; + } + ASSERT_EQ(image.Shape()[0], real_h); // For image in YUV format, each pixel takes 1.5 byte + ASSERT_EQ(image.Shape()[1], real_w); + ASSERT_EQ(image.DataSize(), 1.5 * real_w * real_h); + Transform.DeviceMemoryRelease(); +#endif +} diff --git a/tests/ut/cpp/CMakeLists.txt b/tests/ut/cpp/CMakeLists.txt index 1996dd955c..66a1d2abee 100644 --- a/tests/ut/cpp/CMakeLists.txt +++ b/tests/ut/cpp/CMakeLists.txt @@ -70,6 +70,13 @@ if(ENABLE_MINDDATA) ) list(REMOVE_ITEM UT_SRCS ${PYTHON_RELATED_SRCS}) endif() + + if(NOT ENABLE_ACL) + set(ASCEND310_RELATED_SRCS + dataset/dvpp_decode_jpeg_test.cc + ) + list(REMOVE_ITEM UT_SRCS ${ASCEND310_RELATED_SRCS}) + endif() else() file(GLOB_RECURSE TEMP_UT_SRCS ./*.cc) foreach(OBJ ${TEMP_UT_SRCS}) diff --git a/tests/ut/cpp/dataset/CMakeLists.txt b/tests/ut/cpp/dataset/CMakeLists.txt index e039e1057a..d63ea56b0c 100644 --- a/tests/ut/cpp/dataset/CMakeLists.txt +++ b/tests/ut/cpp/dataset/CMakeLists.txt @@ -149,6 +149,12 @@ if(ENABLE_PYTHON) ) endif() +if(ENABLE_ACL) + set(DE_UT_SRCS + ${DE_UT_SRCS} + dvpp_decode_jpeg_test.cc) +endif() + add_executable(de_ut_tests ${DE_UT_SRCS}) set_target_properties(de_ut_tests PROPERTIES INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/../lib64") diff --git a/tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc b/tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc new file mode 100644 index 0000000000..5f0d37a250 --- /dev/null +++ b/tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc @@ -0,0 +1,40 @@ +/** + * Copyright 2021Huawei Technologies 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 "common/common.h" +#include "common/cvop_common.h" +#include "minddata/dataset/include/vision_ascend.h" +#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h" +#include "utils/log_adapter.h" + +using namespace mindspore::dataset; +using mindspore::LogStream; +using mindspore::ExceptionType::NoExceptionType; +using mindspore::MsLogLevel::INFO; + +class MindDataTestDvppDecodeJpeg : public UT::CVOP::CVOpCommon { + protected: + MindDataTestDvppDecodeJpeg() : CVOpCommon() {} + + std::shared_ptr output_tensor_; +}; + +TEST_F(MindDataTestDvppDecodeJpeg, TestOp1) { + MS_LOG(INFO) << "Doing testDvppDecodeJpeg."; + std::unique_ptr op(new DvppDecodeJpegOp()); + EXPECT_TRUE(op->OneToOne()); + Status s = op->Compute(input_tensor_, &output_tensor_); + EXPECT_EQ(s, Status::OK()); +}