Browse Source

!12183 Dvpp New

From: @lizhenglong1992
Reviewed-by: 
Signed-off-by:
tags/v1.2.0-rc1
mindspore-ci-bot Gitee 4 years ago
parent
commit
b0cc8662c4
49 changed files with 3743 additions and 638 deletions
  1. +235
    -51
      mindspore/ccsrc/minddata/dataset/api/execute.cc
  2. +267
    -0
      mindspore/ccsrc/minddata/dataset/api/vision.cc
  3. +12
    -11
      mindspore/ccsrc/minddata/dataset/core/CMakeLists.txt
  4. +34
    -2
      mindspore/ccsrc/minddata/dataset/core/de_tensor.cc
  5. +7
    -1
      mindspore/ccsrc/minddata/dataset/core/de_tensor.h
  6. +77
    -0
      mindspore/ccsrc/minddata/dataset/core/device_tensor.cc
  7. +65
    -0
      mindspore/ccsrc/minddata/dataset/core/device_tensor.h
  8. +3
    -1
      mindspore/ccsrc/minddata/dataset/core/global_context.cc
  9. +17
    -10
      mindspore/ccsrc/minddata/dataset/core/global_context.h
  10. +16
    -0
      mindspore/ccsrc/minddata/dataset/core/tensor.h
  11. +16
    -3
      mindspore/ccsrc/minddata/dataset/include/execute.h
  12. +0
    -17
      mindspore/ccsrc/minddata/dataset/include/vision.h
  13. +219
    -0
      mindspore/ccsrc/minddata/dataset/include/vision_ascend.h
  14. +6
    -1
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/CMakeLists.txt
  15. +145
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.cc
  16. +62
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h
  17. +139
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.cc
  18. +59
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h
  19. +138
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.cc
  20. +58
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h
  21. +51
    -19
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.cc
  22. +14
    -8
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h
  23. +134
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.cc
  24. +62
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h
  25. +147
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.cc
  26. +63
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h
  27. +0
    -255
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.cc
  28. +0
    -80
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.h
  29. +1
    -1
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CMakeLists.txt
  30. +2
    -12
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h
  31. +392
    -13
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.cc
  32. +32
    -3
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h
  33. +3
    -2
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.cpp
  34. +4
    -4
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h
  35. +966
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.cc
  36. +139
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h
  37. +4
    -5
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.cc
  38. +7
    -7
      mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h
  39. +7
    -1
      mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc
  40. +2
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h
  41. +0
    -99
      mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc
  42. +0
    -19
      mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h
  43. +13
    -0
      mindspore/ccsrc/minddata/dataset/kernels/tensor_op.cc
  44. +18
    -0
      mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h
  45. +3
    -0
      tests/st/cpp/CMakeLists.txt
  46. +51
    -13
      tests/st/cpp/dataset/test_de.cc
  47. +7
    -0
      tests/ut/cpp/CMakeLists.txt
  48. +6
    -0
      tests/ut/cpp/dataset/CMakeLists.txt
  49. +40
    -0
      tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc

+ 235
- 51
mindspore/ccsrc/minddata/dataset/api/execute.cc View File

@@ -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<DeviceTensor> *device_input);

Status Pop(std::shared_ptr<DeviceTensor> device_output, std::shared_ptr<Tensor> *host_output);

Status DeviceDataRelease();

std::shared_ptr<MDAclProcess> processor_;
std::shared_ptr<ResourceManager> 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<MDAclProcess>(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<DeviceTensor> *device_input) {
std::shared_ptr<mindspore::dataset::Tensor> de_input;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(host_input.Shape()),
MSTypeToDEType(static_cast<TypeId>(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<TensorOperation> op) { ops_.emplace_back(std::move(op)); }
Status AscendResource::Pop(std::shared_ptr<DeviceTensor> device_output, std::shared_ptr<Tensor> *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<TensorOperation> 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<AscendResource>();
}
#endif
}

Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> 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<AscendResource>();
}
#endif
}

Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> 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<std::shared_ptr<TensorOp>> transforms;
std::vector<std::shared_ptr<TensorOp>> 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<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()),
MSTypeToDEType(static_cast<TypeId>(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<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()),
MSTypeToDEType(static_cast<TypeId>(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<dataset::Tensor> 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<dataset::Tensor> 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<DETensor>(de_tensor));
} else { // Ascend310 case, where we must set Ascend resource on each operators
#ifdef ENABLE_ACL
std::shared_ptr<mindspore::dataset::DeviceTensor> device_input;
RETURN_IF_NOT_OK(D_resource_->Sink(input, &device_input));
for (auto &t : transforms) {
std::shared_ptr<DeviceTensor> 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<DETensor>(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<DETensor>(device_input, true));
#endif
}
return Status::OK();
}

@@ -82,6 +224,7 @@ Status Execute::operator()(const std::vector<MSTensor> &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<std::shared_ptr<TensorOp>> transforms;
@@ -90,40 +233,81 @@ Status Execute::operator()(const std::vector<MSTensor> &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<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(
dataset::TensorShape(tensor.Shape()), MSTypeToDEType(static_cast<TypeId>(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<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(tensor.Shape()),
MSTypeToDEType(static_cast<TypeId>(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<DETensor>(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<dataset::DeviceTensor> device_input;
RETURN_IF_NOT_OK(D_resource_->Sink(input_tensor, &device_input));
for (auto &t : transforms) {
std::shared_ptr<DeviceTensor> 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<mindspore::dataset::Tensor> host_output;
RETURN_IF_NOT_OK(D_resource_->Pop(device_input, &host_output));
auto ms_tensor = mindspore::MSTensor(std::make_shared<DETensor>(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<DETensor>(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

+ 267
- 0
mindspore/ccsrc/minddata/dataset/api/vision.cc View File

@@ -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<DecodeOperation> Decode(bool rgb) {
}

#ifdef ENABLE_ACL
// Function to create DvppResizeOperation.
std::shared_ptr<DvppCropJpegOperation> DvppCropJpeg(std::vector<uint32_t> crop) {
auto op = std::make_shared<DvppCropJpegOperation>(crop);
// Input validation
return op->ValidateParams() ? op : nullptr;
}

// Function to create DvppDecodeResizeOperation.
std::shared_ptr<DvppDecodeResizeOperation> DvppDecodeResizeJpeg(std::vector<uint32_t> resize) {
auto op = std::make_shared<DvppDecodeResizeOperation>(resize);
// Input validation
return op->ValidateParams() ? op : nullptr;
}

// Function to create DvppDecodeResizeCropOperation.
std::shared_ptr<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vector<uint32_t> crop,
std::vector<uint32_t> resize) {
@@ -150,6 +170,27 @@ std::shared_ptr<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vec
// Input validation
return op->ValidateParams() ? op : nullptr;
}

// Function to create DvppDecodeJpegOperation.
std::shared_ptr<DvppDecodeJpegOperation> DvppDecodeJpeg() {
auto op = std::make_shared<DvppDecodeJpegOperation>();
// Input validation
return op->ValidateParams() ? op : nullptr;
}

// Function to create DvppDecodePngOperation.
std::shared_ptr<DvppDecodePngOperation> DvppDecodePng() {
auto op = std::make_shared<DvppDecodePngOperation>();
// Input validation
return op->ValidateParams() ? op : nullptr;
}

// Function to create DvppResizeOperation.
std::shared_ptr<DvppResizeJpegOperation> DvppResizeJpeg(std::vector<uint32_t> resize) {
auto op = std::make_shared<DvppResizeJpegOperation>(resize);
// Input validation
return op->ValidateParams() ? op : nullptr;
}
#endif

// Function to create EqualizeOperation.
@@ -445,6 +486,232 @@ std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<
}
#endif

#ifdef ENABLE_ACL
// DvppCropOperation
DvppCropJpegOperation::DvppCropJpegOperation(const std::vector<uint32_t> &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<TensorOp> 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<DvppCropJpegOp> tensor_op = std::make_shared<DvppCropJpegOp>(cropHeight, cropWidth);
return tensor_op;
}

// DvppDecodeResizeOperation
DvppDecodeResizeOperation::DvppDecodeResizeOperation(const std::vector<uint32_t> &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<TensorOp> 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<DvppDecodeResizeJpegOp> tensor_op =
std::make_shared<DvppDecodeResizeJpegOp>(resizeHeight, resizeWidth);
return tensor_op;
}

// DvppDecodeResizeCropOperation
DvppDecodeResizeCropOperation::DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop,
const std::vector<uint32_t> &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<TensorOp> 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<DvppDecodeResizeCropJpegOp> tensor_op =
std::make_shared<DvppDecodeResizeCropJpegOp>(cropHeight, cropWidth, resizeHeight, resizeWidth);
return tensor_op;
}

// DvppDecodeJPEG
Status DvppDecodeJpegOperation::ValidateParams() { return Status::OK(); }

std::shared_ptr<TensorOp> DvppDecodeJpegOperation::Build() { return std::make_shared<DvppDecodeJpegOp>(); }

// DvppDecodePNG
Status DvppDecodePngOperation::ValidateParams() { return Status::OK(); }

std::shared_ptr<TensorOp> DvppDecodePngOperation::Build() { return std::make_shared<DvppDecodePngOp>(); }

// DvppResizeOperation
DvppResizeJpegOperation::DvppResizeJpegOperation(const std::vector<uint32_t> &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<TensorOp> 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<DvppResizeJpegOp> tensor_op = std::make_shared<DvppResizeJpegOp>(resizeHeight, resizeWidth);
return tensor_op;
}
#endif

} // namespace vision
} // namespace dataset
} // namespace mindspore

+ 12
- 11
mindspore/ccsrc/minddata/dataset/core/CMakeLists.txt View File

@@ -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)


+ 34
- 2
mindspore/ccsrc/minddata/dataset/core/de_tensor.cc View File

@@ -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<dataset::Tensor> tensor_impl)
: tensor_impl_(tensor_impl),
name_("MindDataTensor"),
type_(static_cast<mindspore::DataType>(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<dataset::DeviceTensor> 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<int64_t>(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<int64_t> &DETensor::Shape() const { return shape_; }

std::shared_ptr<const void> DETensor::Data() const {
#ifndef ENABLE_ANDROID
if (is_device_) {
return std::shared_ptr<const void>(device_tensor_impl_->GetDeviceBuffer(), [](const void *) {});
}
#endif
return std::shared_ptr<const void>(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<mindspore::MSTensor::Impl> DETensor::Clone() const { return std::make_shared<DETensor>(tensor_impl_); }
} // namespace dataset


+ 7
- 1
mindspore/ccsrc/minddata/dataset/core/de_tensor.h View File

@@ -31,7 +31,9 @@ class DETensor : public mindspore::MSTensor::Impl {
DETensor() = default;
~DETensor() override = default;
explicit DETensor(std::shared_ptr<dataset::Tensor> tensor_impl);

#ifndef ENABLE_ANDROID
explicit DETensor(std::shared_ptr<dataset::DeviceTensor> 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<dataset::Tensor> tensor_impl_;
#ifndef ENABLE_ANDROID
std::shared_ptr<dataset::DeviceTensor> device_tensor_impl_;
#endif
bool is_device_;
std::string name_;
enum mindspore::DataType type_;
std::vector<int64_t> shape_;


+ 77
- 0
mindspore/ccsrc/minddata/dataset/core/device_tensor.cc View File

@@ -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<uint32_t> DeviceTensor::GetYuvStrideShape() { return YUV_shape_; }

#ifdef ENABLE_ACL
Status DeviceTensor::SetAttributes(const std::shared_ptr<DvppDataInfo> &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<MemoryPool> global_pool = GlobalContext::Instance()->mem_pool();
data_allocator_ = std::make_unique<Allocator<unsigned char>>(global_pool);
}

Status DeviceTensor::CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr<DeviceTensor> *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<DeviceTensor>(*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

+ 65
- 0
mindspore/ccsrc/minddata/dataset/core/device_tensor.h View File

@@ -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 <memory>
#include <utility>
#include <vector>
#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<DvppDataInfo> &data);
#endif
static Status CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr<DeviceTensor> *out);

uint8_t *GetDeviceBuffer();

std::vector<uint32_t> 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<uint32_t> YUV_shape_;
uint8_t *device_data_;
uint32_t size_;
};

} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_DEVICE_TENSOR_H

+ 3
- 1
mindspore/ccsrc/minddata/dataset/core/global_context.cc View File

@@ -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<Allocator<CVTensor>>(mem_pool_);
#endif
device_tensor_allocator_ = std::make_unique<Allocator<DeviceTensor>>(mem_pool_);
int_allocator_ = std::make_unique<IntAlloc>(mem_pool_);
return Status::OK();
}


+ 17
- 10
mindspore/ccsrc/minddata/dataset/core/global_context.h View File

@@ -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 <memory>
#include <mutex>

#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<Tensor>; // An allocator for Tensors
using CVTensorAlloc = Allocator<CVTensor>; // An allocator CVTensors
using TensorAlloc = Allocator<Tensor>; // An allocator for Tensors
using CVTensorAlloc = Allocator<CVTensor>; // An allocator CVTensors
using DeviceTensorAlloc = Allocator<DeviceTensor>; // An allocator for Device_Tensors
using IntAlloc = Allocator<dsize_t>;

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<GlobalContext> global_context_; // The instance of the singleton (global)
std::shared_ptr<MemoryPool> mem_pool_; // A global memory pool
std::shared_ptr<ConfigManager> config_manager_; // The configs
std::unique_ptr<TensorAlloc> tensor_allocator_; // An allocator for Tensors
std::unique_ptr<CVTensorAlloc> cv_tensor_allocator_; // An allocator for CV Tensors
std::unique_ptr<IntAlloc> int_allocator_; // An allocator for ints
static std::unique_ptr<GlobalContext> global_context_; // The instance of the singleton (global)
std::shared_ptr<MemoryPool> mem_pool_; // A global memory pool
std::shared_ptr<ConfigManager> config_manager_; // The configs
std::unique_ptr<TensorAlloc> tensor_allocator_; // An allocator for Tensors
std::unique_ptr<CVTensorAlloc> cv_tensor_allocator_; // An allocator for CV Tensors
std::unique_ptr<DeviceTensorAlloc> device_tensor_allocator_; // An allocator for Device Tensors
std::unique_ptr<IntAlloc> int_allocator_; // An allocator for ints
};
} // namespace dataset
} // namespace mindspore


+ 16
- 0
mindspore/ccsrc/minddata/dataset/core/tensor.h View File

@@ -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<uint32_t> tmp{width, widthStride, height, heightStride};
yuv_shape_ = tmp;
return Status::OK();
}

std::vector<uint32_t> 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<uint32_t> yuv_shape_;
#endif

private:
friend class DETensor;



+ 16
- 3
mindspore/ccsrc/minddata/dataset/include/execute.h View File

@@ -17,25 +17,28 @@
#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_EXECUTE_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_EXECUTE_H_

#include <string>
#include <vector>
#include <memory>
#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<TensorOperation> op);
explicit Execute(std::shared_ptr<TensorOperation> op, std::string deviceType = "CPU");

explicit Execute(std::vector<std::shared_ptr<TensorOperation>> ops);
explicit Execute(std::vector<std::shared_ptr<TensorOperation>> 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<mindspore::MSTensor> &input_tensor_list, std::vector<mindspore::MSTensor> *out);
#ifdef ENABLE_ACL
Status DeviceMemoryRelease();
#endif

private:
Status validate_device_();

std::vector<std::shared_ptr<TensorOperation>> ops_;

std::string device_type_;
#ifdef ENABLE_ACL
std::shared_ptr<AscendResource> D_resource_;
#endif
};

} // namespace dataset


+ 0
- 17
mindspore/ccsrc/minddata/dataset/include/vision.h View File

@@ -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<CutMixBatchOperation> CutMixBatch(ImageBatchFormat image_batch_f
/// \return Shared pointer to the current TensorOp
std::shared_ptr<CutOutOperation> 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<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vector<uint32_t> crop = {224, 224},
std::vector<uint32_t> resize = {256, 256});

/// \brief Function to create a Equalize TensorOperation.
/// \notes Apply histogram equalization on input image.
/// \return Shared pointer to the current TensorOperation.


+ 219
- 0
mindspore/ccsrc/minddata/dataset/include/vision_ascend.h View File

@@ -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 <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#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<DvppCropJpegOperation> DvppCropJpeg(std::vector<uint32_t> 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<DvppDecodeResizeOperation> DvppDecodeResizeJpeg(std::vector<uint32_t> 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<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vector<uint32_t> crop = {224, 224},
std::vector<uint32_t> 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<DvppDecodeJpegOperation> 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<DvppDecodePngOperation> 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<DvppResizeJpegOperation> DvppResizeJpeg(std::vector<uint32_t> resize = {256, 256});

class DvppCropJpegOperation : public TensorOperation {
public:
explicit DvppCropJpegOperation(const std::vector<uint32_t> &resize);

~DvppCropJpegOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppCropJpegOperation; }

private:
std::vector<uint32_t> crop_;
};

class DvppDecodeResizeOperation : public TensorOperation {
public:
explicit DvppDecodeResizeOperation(const std::vector<uint32_t> &resize);

~DvppDecodeResizeOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppDecodeResizeOperation; }

private:
std::vector<uint32_t> resize_;
};

class DvppDecodeResizeCropOperation : public TensorOperation {
public:
explicit DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop, const std::vector<uint32_t> &resize);

~DvppDecodeResizeCropOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppDecodeResizeCropOperation; }

private:
std::vector<uint32_t> crop_;
std::vector<uint32_t> resize_;
};

class DvppDecodeJpegOperation : public TensorOperation {
public:
~DvppDecodeJpegOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppDecodeJpegOperation; }
};

class DvppDecodePngOperation : public TensorOperation {
public:
~DvppDecodePngOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppDecodePngOperation; }
};

class DvppResizeJpegOperation : public TensorOperation {
public:
explicit DvppResizeJpegOperation(const std::vector<uint32_t> &resize);

~DvppResizeJpegOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppResizeJpegOperation; }

private:
std::vector<uint32_t> resize_;
};
} // namespace vision
} // namespace dataset
} // namespace mindspore

#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_ASCEND_H_

+ 6
- 1
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/CMakeLists.txt View File

@@ -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)

+ 145
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.cc View File

@@ -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 <string>
#include <vector>
#include <iostream>
#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<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *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<DvppDataInfo> 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<DvppDataInfo> 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<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
DvppDataInfo imageinfo;
imageinfo.dataSize = input->SizeInBytes();
imageinfo.data = static_cast<uint8_t *>(buffer);
std::vector<uint32_t> 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<ResourceManager> 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<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> 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<TensorShape> &inputs, std::vector<TensorShape> &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<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetCropParas(crop_width_, crop_height_);
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

+ 62
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h View File

@@ -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 <memory>
#include <string>
#include <vector>
#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<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppCropJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
uint32_t crop_height_;
uint32_t crop_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_CROP_JPEG_OP_H

+ 139
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.cc View File

@@ -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 <string>
#include <vector>
#include <iostream>
#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<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *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<DvppDataInfo> 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<Tensor> &input, std::shared_ptr<Tensor> *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<unsigned char *>(input->GetBuffer());
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> 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<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> 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<MDAclProcess> &processor) {
processor_ = processor;
return Status::OK();
}
Status DvppDecodeJpegOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &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

+ 59
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h View File

@@ -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 <memory>
#include <string>
#include <vector>
#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<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_JPEG_OP_H

+ 138
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.cc View File

@@ -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 <string>
#include <vector>
#include <iostream>
#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<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *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<DvppDataInfo> 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<Tensor> &input, std::shared_ptr<Tensor> *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<unsigned char *>(input->GetBuffer());
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> 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<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> 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<TensorShape> &inputs, std::vector<TensorShape> &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<MDAclProcess> &processor) {
processor_ = processor;
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

+ 58
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h View File

@@ -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 <memory>
#include <string>
#include <vector>
#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<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodePngOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_PNG_OP_H

+ 51
- 19
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.cc View File

@@ -17,20 +17,48 @@
#include <string>
#include <vector>
#include <iostream>
#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<DeviceTensor> &input,
std::shared_ptr<DeviceTensor> *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<DvppDataInfo> 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<Tensor> &input, std::shared_ptr<Tensor> *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<Tensor> &input,
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = std::make_shared<uint8_t>();
imageInfo.data.reset(new uint8_t[filesize], std::default_delete<uint8_t[]>());
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<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
@@ -56,25 +80,26 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr<Tensor> &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<unsigned char>(process.Get_Memory_Data());
auto data = std::static_pointer_cast<unsigned char>(processor.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> CropOut = process.Get_Device_Memory_Data();
dsize_t dvpp_length = CropOut->dataSize;
std::shared_ptr<DvppDataInfo> 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<Tensor> &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<TensorShape> &i
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}

Status DvppDecodeResizeCropJpegOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetResizeParas(resized_width_, resized_height_);
processor_->SetCropParas(crop_width_, crop_height_);
return Status::OK();
}

} // namespace dataset
} // namespace mindspore

+ 14
- 8
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h View File

@@ -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 <memory>
#include <string>
#include <vector>

#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<Tensor> &input, std::shared_ptr<Tensor> *output) override;

Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;

Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;

std::string Name() const override { return kDvppDecodeResizeCropJpegOp; }

Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;

private:
int32_t crop_height_;
int32_t crop_width_;
int32_t resized_height_;
int32_t resized_width_;
std::shared_ptr<MDAclProcess> 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

+ 134
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.cc View File

@@ -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 <string>
#include <vector>
#include <iostream>
#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<DeviceTensor> &input,
std::shared_ptr<DeviceTensor> *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<DvppDataInfo> 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<Tensor> &input, std::shared_ptr<Tensor> *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<unsigned char *>(input->GetBuffer());
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> 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<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> 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<TensorShape> &inputs, std::vector<TensorShape> &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<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetResizeParas(resized_width_, resized_height_);
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

+ 62
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h View File

@@ -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 <memory>
#include <string>
#include <vector>
#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<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeResizeJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
int32_t resized_height_;
int32_t resized_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H

+ 147
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.cc View File

@@ -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 <string>
#include <vector>
#include <iostream>
#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<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *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<DvppDataInfo> 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<DvppDataInfo> 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<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
DvppDataInfo imageinfo;
imageinfo.dataSize = input->SizeInBytes();
imageinfo.data = static_cast<uint8_t *>(buffer);
std::vector<uint32_t> 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<ResourceManager> 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<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> 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<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetResizeParas(resized_width_, resized_height_);
return Status::OK();
}
Status DvppResizeJpegOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &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

+ 63
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h View File

@@ -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 <memory>
#include <string>
#include <vector>
#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<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeResizeJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
int32_t resized_height_;
int32_t resized_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_RESIZE_JPEG_OP_H

+ 0
- 255
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.cc View File

@@ -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 <sys/stat.h>
#include <sys/time.h>
#include <thread>

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> 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<DvppCommon>(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<DvppDataInfo> 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<DvppDataInfo> 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<DvppDataInfo> 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<void> 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<void> AclProcess::Get_Memory_Data() { return processedInfo_; }

std::shared_ptr<DvppDataInfo> 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(); }

+ 0
- 80
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/AclProcess.h View File

@@ -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 <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
#include <string>
#include <map>
#include <climits>
#include <iostream>
#include <memory>
#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> 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<void> Get_Memory_Data();
// API for access device memory
std::shared_ptr<DvppDataInfo> 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> dvppCommon_; // dvpp object
std::shared_ptr<void> 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

+ 1
- 1
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CMakeLists.txt View File

@@ -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


+ 2
- 12
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h View File

@@ -21,7 +21,6 @@
#include <stdio.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#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<int64_t> 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<void> data; // Smart pointer of data
size_t lenOfByte; // Size of memory, bytes
void *data; // Pointer of data
};

// Description of data in device


+ 392
- 13
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.cc View File

@@ -15,6 +15,7 @@

#include <iostream>
#include <memory>

#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<DvppDataInfo>();
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<DvppDataInfo>();
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<DvppDataInfo> &input,
std::shared_ptr<DvppDataInfo> &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<DvppDataInfo> &input,
std::shared_ptr<DvppDataInfo> &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<DvppDataInfo>();
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<DvppDataInfo>();
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<DvppDataInfo>();
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<DvppDataInfo> &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<DvppDataInfo>();
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<DvppDataInfo>();
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<DvppDataInfo>();
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<DvppDataInfo>();
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


+ 32
- 3
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h View File

@@ -16,8 +16,6 @@
#ifndef DVPP_COMMON_H
#define DVPP_COMMON_H

#include <vector>
#include <memory>
#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<DvppDataInfo> &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<DvppDataInfo> &input, std::shared_ptr<DvppDataInfo> &output,
bool withSynchronize);
APP_ERROR SinkCombinePngdProcess(std::shared_ptr<DvppDataInfo> &input, std::shared_ptr<DvppDataInfo> &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<DvppDataInfo> data, void *userData);

@@ -168,6 +189,15 @@ class DvppCommon {
std::shared_ptr<DvppDataInfo> GetEncodedImage();
std::shared_ptr<DvppDataInfo> 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<DvppDataInfo> &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<DvppDataInfo> &jpegInput);
APP_ERROR CreateStreamDesc(std::shared_ptr<DvppDataInfo> data);
APP_ERROR DestroyResource();



+ 3
- 2
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.cpp View File

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


+ 4
- 4
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h View File

@@ -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_

+ 966
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.cc View File

@@ -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 <sys/time.h>
#include <thread>
#include <sys/stat.h>

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> 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> 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> 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<DvppCommon>(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<DvppCommon> 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<mindspore::dataset::Tensor> &input,
std::shared_ptr<mindspore::dataset::DeviceTensor> &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<unsigned char *>(input->GetBuffer());
imageinfo.data = static_cast<void *>(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<mindspore::dataset::DeviceTensor> &device_output,
std::shared_ptr<mindspore::dataset::Tensor> &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<void> 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<unsigned char>(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<DvppDataInfo> 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<void> 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<DvppDataInfo> 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<DvppDataInfo> 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<void> 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<DvppDataInfo> 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<DvppDataInfo> 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<DvppDataInfo> input_image = std::make_shared<DvppDataInfo>();
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<DvppDataInfo> 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<void> 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<DvppDataInfo> 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<DvppDataInfo> 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<DvppDataInfo> input_image = std::make_shared<DvppDataInfo>();
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<DvppDataInfo> 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<void> 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<DvppDataInfo> 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<DvppDataInfo> 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<void> 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<DvppDataInfo> 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<DvppDataInfo> 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<DvppDataInfo> 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<DvppDataInfo> 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<void> 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<DvppDataInfo> 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<DvppDataInfo> 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<void> MDAclProcess::Get_Memory_Data() { return processedInfo_; }

std::shared_ptr<DvppDataInfo> MDAclProcess::Get_Croped_DeviceData() { return dvppCommon_->GetCropedImage(); }

std::shared_ptr<DvppDataInfo> MDAclProcess::Get_Resized_DeviceData() { return dvppCommon_->GetResizedImage(); }

std::shared_ptr<DvppDataInfo> 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<uint32_t> MDAclProcess::Get_Primary_Shape() {
std::vector<uint32_t> pri_shape;
if (!dvppCommon_) {
pri_shape.emplace_back(dvppCommon_->GetDecodedImage()->heightStride);
pri_shape.emplace_back(dvppCommon_->GetDecodedImage()->widthStride);
}
return pri_shape;
}

+ 139
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h View File

@@ -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 <climits>
#include <string>
#include <string.h>
#include <map>
#include <iostream>
#include <memory>
#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 <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

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> dvppCommon = nullptr);

MDAclProcess(uint32_t ParaWidth, uint32_t ParaHeight, aclrtContext context, bool is_crop = false,
aclrtStream stream = nullptr, std::shared_ptr<DvppCommon> dvppCommon = nullptr);

MDAclProcess(aclrtContext context, bool is_crop = false, aclrtStream stream = nullptr,
std::shared_ptr<DvppCommon> 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<void> Get_Memory_Data();
// API for access device memory of croped data
std::shared_ptr<DvppDataInfo> Get_Croped_DeviceData();
// API for access device memory of resized data
std::shared_ptr<DvppDataInfo> Get_Resized_DeviceData();
// API for access device memory of decode data
std::shared_ptr<DvppDataInfo> Get_Decode_DeviceData();

APP_ERROR H2D_Sink(std::shared_ptr<mindspore::dataset::Tensor> &input,
std::shared_ptr<mindspore::dataset::DeviceTensor> &device_input);

APP_ERROR D2H_Pop(std::shared_ptr<mindspore::dataset::DeviceTensor> &device_output,
std::shared_ptr<mindspore::dataset::Tensor> &output);

// D-chip memory release
APP_ERROR device_memory_release();

std::shared_ptr<DvppCommon> GetDeviceModule();

std::vector<uint32_t> 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> dvppCommon_; // dvpp object
std::shared_ptr<void> 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

+ 4
- 5
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.cc View File

@@ -29,15 +29,15 @@ std::shared_ptr<ResourceManager> 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) {


+ 7
- 7
mindspore/ccsrc/minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h View File

@@ -16,20 +16,18 @@
#ifndef RESOURCEMANAGER_H
#define RESOURCEMANAGER_H

#include <sys/stat.h>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <unordered_map>
#include <memory>
#include <mutex>
#include "CommonDataType.h"
#include "ErrorCode.h"
#include <sys/stat.h>
#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<ResourceManager> GetInstance();
@@ -89,4 +89,4 @@ class ResourceManager {
std::shared_ptr<mindspore::AclEnvGuard> acl_env_;
};

#endif
#endif

+ 7
- 1
mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc View File

@@ -142,6 +142,12 @@ bool IsNonEmptyJPEG(const std::shared_ptr<Tensor> &input) {
return input->SizeInBytes() > kJpegMagicLen && memcmp(input->GetBuffer(), kJpegMagic, kJpegMagicLen) == 0;
}

bool IsNonEmptyPNG(const std::shared_ptr<Tensor> &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<Tensor> &input, std::shared_ptr<Tensor> *output) {
if (IsNonEmptyJPEG(input)) {
return JpegCropAndDecode(input, output);
@@ -953,7 +959,7 @@ Status Erase(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *outp
RETURN_STATUS_UNEXPECTED("CutOut: load image failed.");
}
if (input_cv->Rank() != 3 || num_channels != 3) {
RETURN_STATUS_UNEXPECTED("CutOut: image shape is not <H,W,C>.");
RETURN_STATUS_UNEXPECTED("CutOut: image shape is not <H,W,C> or <H,W>.");
}
cv::Mat input_img = input_cv->mat();
int32_t image_h = input_cv->shape()[0];


+ 2
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h View File

@@ -103,6 +103,8 @@ Status DecodeCv(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *o

bool IsNonEmptyJPEG(const std::shared_ptr<Tensor> &input);

bool IsNonEmptyPNG(const std::shared_ptr<Tensor> &input);

void JpegSetSource(j_decompress_ptr c_info, const void *data, int64_t data_size);

Status JpegCropAndDecode(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int x = 0, int y = 0,


+ 0
- 99
mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc View File

@@ -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<uint32_t> &crop,
const std::vector<uint32_t> &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<TensorOp> 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<DvppDecodeResizeCropJpegOp> tensor_op =
std::make_shared<DvppDecodeResizeCropJpegOp>(cropHeight, cropWidth, resizeHeight, resizeWidth);
return tensor_op;
}
#endif

// NormalizeOperation
NormalizeOperation::NormalizeOperation(std::vector<float> mean, std::vector<float> std) : mean_(mean), std_(std) {}



+ 0
- 19
mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h View File

@@ -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<uint32_t> &crop, const std::vector<uint32_t> &resize);

~DvppDecodeResizeCropOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kDvppDecodeResizeCropOperation; }

private:
std::vector<uint32_t> crop_;
std::vector<uint32_t> resize_;
};

class EqualizeOperation : public TensorOperation {
public:
~EqualizeOperation() = default;


+ 13
- 0
mindspore/ccsrc/minddata/dataset/kernels/tensor_op.cc View File

@@ -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<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *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<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
if (inputs.size() != NumInput())
return Status(StatusCode::kMDUnexpectedError,
@@ -63,5 +70,11 @@ Status TensorOp::OutputType(const std::vector<DataType> &inputs, std::vector<Dat
outputs = inputs;
return Status::OK();
}
#ifdef ENABLE_ACL
Status TensorOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &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

+ 18
- 0
mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h View File

@@ -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<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *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<MDAclProcess> &processor);
#endif

protected:
bool is_deterministic_{true};


+ 3
- 0
tests/st/cpp/CMakeLists.txt View File

@@ -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)


+ 51
- 13
tests/st/cpp/dataset/test_de.cc View File

@@ -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<mindspore::dataset::DETensor>(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<mindspore::dataset::DETensor>(de_tensor));

// Define dvpp transform
std::vector<uint32_t> crop_size = {224, 224};
std::vector<uint32_t> resize_size = {256, 256};
mindspore::dataset::Execute Transform(DvppDecodeResizeCropJpeg(crop_size, resize_size));
std::vector<uint32_t> crop_paras = {224, 224};
std::vector<uint32_t> 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<mindspore::dataset::Tensor> de_tensor;
mindspore::dataset::Tensor::CreateFromFile("./data/dataset/apple.jpg", &de_tensor);
auto image = MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));

// Define dvpp transform
std::vector<uint32_t> crop_paras = {224, 224};
std::vector<uint32_t> 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
}

+ 7
- 0
tests/ut/cpp/CMakeLists.txt View File

@@ -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})


+ 6
- 0
tests/ut/cpp/dataset/CMakeLists.txt View File

@@ -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")


+ 40
- 0
tests/ut/cpp/dataset/dvpp_decode_jpeg_test.cc View File

@@ -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<Tensor> output_tensor_;
};

TEST_F(MindDataTestDvppDecodeJpeg, TestOp1) {
MS_LOG(INFO) << "Doing testDvppDecodeJpeg.";
std::unique_ptr<DvppDecodeJpegOp> op(new DvppDecodeJpegOp());
EXPECT_TRUE(op->OneToOne());
Status s = op->Compute(input_tensor_, &output_tensor_);
EXPECT_EQ(s, Status::OK());
}

Loading…
Cancel
Save