Typical Functions of VPC

This section takes image cropping and resizing as an example to explain the API call sequence when the VPC processes images and provides sample code of typical functions to help you better understand the API call sequence.

Vision Preprocessing Core (VPC) supports image cropping, resizing, pasting, and format conversion. For details about the VPC functions and restrictions, see DVPP Media Acceleration Library.

API Call Sequence (Image Resizing)

Figure 1 API call sequence for image resizing

The current system supports image cropping and resizing. The key APIs are described as follows:

  1. Call aclInit to initialize the system.
  2. Call aclrtSetDevice to specify the compute device.
  3. Call hi_mpi_sys_init to initialize the media data processing system.
  4. Call hi_mpi_vpc_sys_create_chn to create a channel.
  5. Call hi_mpi_dvpp_malloc to allocate the device memory to store the input or output data.
  6. Execute the image processing task. The following uses image resizing as an example.

    Call hi_mpi_vpc_resize to resize the image. hi_mpi_vpc_resize is an asynchronous API. The API call only delivers a task. You also need to call hi_mpi_vpc_get_process_result to obtain the processing result.

    • You can call hi_mpi_vpc_get_process_result in the same thread as hi_mpi_vpc_resize, or start a new thread. Multiple threads can improve efficiency, but require inter-thread synchronization.
    • When calling the resizing API, you can set different formats for the input and output images, achieving image format conversion.
    • If the DVPP APIs are called on the host, the image processing result will be stored in the device memory. To access the resultant data, you need to transfer it back to the host.
  7. Call hi_mpi_dvpp_free to free the input and output buffers.
  8. Call hi_mpi_vpc_destroy_chn to destroy the channel.
  9. Call hi_mpi_sys_exit to deinitialize the media data processing system.
  10. Call aclrtResetDevice to reset the device and free the resources on the device.
  11. Call aclFinalize to deinitialize the system and free the resources used by the acl API in the process.

Sample Code for Image Resizing

The following is a code snippet of key steps for image resizing. It is for reference only. Do not copy, build, or run it directly. After APIs are called, you need to add exception handling branches and record error logs and info logs.

You can click vpc_sample to obtain the sample.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// ....

// 1. Initialize the media data processing system.
int32_t ret = hi_mpi_sys_init();

// 2. Create a channel.
hi_vpc_chn chnId;
hi_vpc_chn_attr stChnAttr;
ret = hi_mpi_vpc_sys_create_chn(&chnId, &stChnAttr);

// 3. Perform resizing.
// 3.1 Construct a struct for storing input image information.
hi_vpc_pic_info inputPic;
inputPic.picture_width = 1920;
inputPic.picture_height = 1080;
inputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
inputPic.picture_width_stride = 1920;
inputPic.picture_height_stride = 1080;
inputPic.picture_buffer_size = inputPic.picture_width_stride * inputPic.picture_height_stride * 3 / 2;

// 3.2 Prepare input image data.
// Load the input image into the device memory. The ReadPicFile function is defined by the user.
ReadPicFile(picName, inputPic.picture_address, inputPic.picture_buffer_size);

// 3.3 Construct a struct for storing output image information.
hi_vpc_pic_info outputPic;
outputPic.picture_width = 960;
outputPic.picture_height  = 540;
outputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
outputPic.picture_width_stride = 960;
outputPic.picture_height_stride = 540;
outputPic.picture_buffer_size = outputPic.picture_width_stride * outputPic.picture_height_stride * 3 / 2;
ret = hi_mpi_dvpp_malloc(0, &outputPic.picture_address, outputPic.picture_buffer_size);

// Initialize the buffer.
memset(outputPic.picture_address, 0, outputPic.picture_buffer_size);

// 3.4 Call the image resizing API.
uint32_t taskID = 0;
ret = hi_mpi_vpc_resize(chnId, &inputPic, &outputPic, 0, 0, 0, &taskID, -1);

// 3.5 Wait until the task processing is complete. The output image data is stored in the buffer specified by outputPic.picture_address.
uint32_t taskIDResult = taskID;
ret = hi_mpi_vpc_get_process_result(chnId, taskIDResult, -1);

// 3.6 The output image data of VPC can be directly used as the input for model inference.
// You can directly use the output image data of VPC in the buffer specified by outputPic.picture_address.
    // TODO: inference-related code logic


// 3.7 Free the input and output buffers.
ret = hi_mpi_dvpp_free(inputPic.picture_address);
ret = hi_mpi_dvpp_free(outputPic.picture_address);

// 4. Destroy the channel.
ret = hi_mpi_vpc_destroy_chn(chnId);

// 5. Deinitialize the media data processing system.
ret = hi_mpi_sys_exit();

// ....

Sample Code for Image Cropping

The following is a code snippet of key steps for image cropping. It is for reference only. Do not copy, build, or run it directly. After APIs are called, you need to add exception handling branches and record error logs and info logs.

You can click vpc_sample to obtain the sample.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// ....

// 1. Initialize the media data processing system.
int32_t ret = hi_mpi_sys_init();

// 2. Create a channel.
hi_vpc_chn chnId;
hi_vpc_chn_attr stChnAttr;
ret = hi_mpi_vpc_sys_create_chn(&chnId, &stChnAttr);

// 3. Perform image cropping.
// 3.1 Construct a struct for storing input image information.
hi_vpc_pic_info inputPic;
inputPic.picture_width = 1920;
inputPic.picture_height = 1080;
inputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
inputPic.picture_width_stride = 1920;
inputPic.picture_height_stride = 1080;
inputPic.picture_buffer_size = inputPic.picture_width_stride * inputPic.picture_height_stride * 3 / 2;

// 3.2 Prepare input image data.
// Allocate the device memory for media data processing.
ret = hi_mpi_dvpp_malloc(0, &inputPic.picture_address, inputPic.picture_buffer_size);

// Load the input image into the device memory. The ReadPicFile function is defined by the user.
ReadPicFile(picName, inputPic.picture_address, inputPic.picture_buffer_size);

// 3.3 Construct a struct for storing output image information.
//This parameter indicates the number of crop ROIs.
uint32_t multiCount = 1;
// The size of the cropRegionInfos array must be consistent with the number of crop ROIs.
hi_vpc_crop_region_info cropRegionInfos[1];
hi_vpc_pic_info outputPic;
for (uint32_t i = 0; i < multiCount; i++) {
    outputPic.picture_width = 960;
    outputPic.picture_height  = 540;
    outputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
    outputPic.picture_width_stride = 960;
    outputPic.picture_height_stride = 540;
    outputPic.picture_buffer_size = outputPic.picture_width_stride * outputPic.picture_height_stride * 3 / 2;
    ret = hi_mpi_dvpp_malloc(0, &outputPic.picture_address, outputPic.picture_buffer_size);

// Initialize the buffer.
    memset(outputPic.picture_address, 0, outputPic.picture_buffer_size);
    
    // Crop a 960 x 540 ROI from the input image with the upper-left corner as the origin.
    cropRegionInfos[i].dest_pic_info = outputPic;
    cropRegionInfos[i].crop_region.left_offset = 0;
    cropRegionInfos[i].crop_region.top_offset = 0;
    cropRegionInfos[i].crop_region.crop_width = 960;
    cropRegionInfos[i].crop_region.crop_height = 540;
}

// 3.4 Call the image cropping API.
uint32_t taskID = 0;
ret = hi_mpi_vpc_crop(chnId, &inputPic, cropRegionInfos, 1, &taskID, -1);

// 3.5 Wait until the task processing is complete. The output image data is stored in the buffer specified by outputPic.picture_address.
uint32_t taskIDResult = taskID;
ret = hi_mpi_vpc_get_process_result(chnId, taskIDResult, -1);

// 3.6 The output image data of VPC can be directly used as the input for model inference.
// You can directly use the output image data of VPC in the buffer specified by outputPic.picture_address.
    // TODO: inference-related code logic

// 3.7 Free the input and output buffers.
ret = hi_mpi_dvpp_free(inputPic.picture_address);
inputPic.picture_address = nullptr;
for (uint32_t i = 0; i < multiCount; i++) {
     hi_mpi_dvpp_free(cropRegionInfos[i].dest_pic_info.picture_address);
     cropRegionInfos[i].dest_pic_info.picture_address = nullptr;
}

// 4. Destroy the channel.
ret = hi_mpi_vpc_destroy_chn(chnId);

// 5. Deinitialize the media data processing system.
ret = hi_mpi_sys_exit();

// ....