PNGD

This section describes the API call sequence of PNGD, and sample code is also provided to help you better understand the process.

The PNG decoder (PNGD) decodes images in PNG format. For details about the PNGD function and restrictions, see DVPP Media Acceleration Library.

API Call Sequence

Figure 1 Process of calling the PNGD function

The current system supports decoding PNG images. The key APIs are described as follows:

  1. Call aclInit to initialize the system.
  2. Call aclrtSetDevice to specify the compute device.
  3. Call the hi_mpi_sys_init interface to initialize the media data processing system.
  4. Call the hi_mpi_pngd_create_chn API to create a channel.
  5. Call the hi_mpi_dvpp_malloc API to allocate memory on the device to store the input or output data.
  6. Invoke the hi_mpi_pngd_send_stream interface to send the decoding stream. The hi_mpi_pngd_send_stream interface is an asynchronous interface. If this interface is invoked, the task is successfully delivered. In addition, the hi_mpi_pngd_get_image_data interface needs to be invoked to obtain the decoding result.
  7. Call the hi_mpi_dvpp_free interface to release the input and output buffers.
  8. Destroy the channel by calling hi_mpi_pngd_destroy_chn.
  9. Deinitialize the media data processing system by calling hi_mpi_sys_exit.
  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

The following is a code example of key steps of PNGD image decoding. It is for reference only and cannot be directly copied for compilation and running. After APIs are called, you need to add exception handling branches and record error logs and info logs.

You can click pngd_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
81
// 1. Initialize the media data processing system.
int32_t ret = hi_mpi_sys_init();

// 2. Create a channel.
hi_pngd_chn chnId;
hi_pngd_chn_attr chnAttr; // hi_pngd_chn_attr is a reserved parameter and does not need to be set.
ret = hi_mpi_pngd_create_chn(chnId, &chnAttr);

// 3. Send the stream.
// 3.1 Allocate input buffer.
uint8_t* inputAddr = nullptr;
//inputsize indicates the buffer size occupied by the input image. The following uses 1024 bytes as an example. You need to calculate the actual buffer size.
int32_t inputSize = 1024;
ret = hi_mpi_dvpp_malloc(0, &inputAddr, inputSize);
// Read the input image to the memory. The user-defined function ReadStreamFile is implemented by the user.
ReadStreamFile(fileName, inputAddr, inputSize);

// 3.2 Construct a structure for storing input image information.
hi_img_stream stStream{};
hi_img_info stImgInfo{};
stStream.pts = 0;
if (g_runMode == ACL_HOST) {
    stStream.addr  = (uint8_t *)hostInputAddr;
} else {
    stStream.addr  = (uint8_t *)inputAddr;
}
stStream.len  = inputSize;
stStream.type = HI_PT_PNG;

ret = hi_mpi_png_get_image_info(&stStream, &stImgInfo);
if (g_runMode == ACL_HOST) {
    // If the data on the host is not used, free the host buffer in a timely manner.
   aclrtFreeHost(hostInputAddr);
    hostInputAddr = nullptr;
}
stStream.addr = (uint8_t *)inputAddr;

// 3.3 Construct a structure for storing the output image information and allocate the output buffer.
hi_pic_info outPicInfo{};
void *outBuffer = nullptr;
outPicInfo.picture_width  = stImgInfo.width;
outPicInfo.picture_height = stImgInfo.height;
outPicInfo.picture_width_stride  = stImgInfo.width_stride;
outPicInfo.picture_height_stride = stImgInfo.height_stride;
outPicInfo.picture_buffer_size   = stImgInfo.img_buf_size;
outPicInfo.picture_format = HI_PIXEL_FORMAT_UNKNOWN;

ret = hi_mpi_dvpp_malloc(0, &outBuffer, outPicInfo.buffer_size);

outPicInfo.picture_address = (uint64_t)outBuffer;

// 3.4 Send the input image to be decoded.
ret = hi_mpi_pngd_send_stream(chnId, &stream, &outPicInfo, 0);

// 4. Receive the decoding result.
// 4.1 Obtain the decoding result.
hi_pic_info picInfo;
hi_img_stream stream;
ret = hi_mpi_pngd_get_image_data(chnId, &picInfo, &stream, 0);
if (ret == HI_SUCCESS) { // Decode success
    printf("[%s][%d] Chn %u GetFrame Success, Decode Success \n",__FUNCTION__, __LINE__, chnId);
} else if (ret == HI_ERR_PNGD_BUF_EMPTY){ // Decoding
    printf("[%s][%d] Chn %u Decoding, try again \n",__FUNCTION__, __LINE__, chnId);
} else { // Decode fail
    printf("[%s][%d] Chn %u GetFrame Success, Decode Fail \n",__FUNCTION__, __LINE__, chnId);
}

// 4.2 Obtain the PNGD output image data, which is stored in the memory specified by outputPic.picture_address.
......

// 4.3 Release the input and output buffers.
ret = hi_mpi_dvpp_free(frame.v_frame.virt_addr[0]);
ret = hi_mpi_dvpp_free(stream.addr);

// 5. Destroy the channel.
ret = hi_mpi_pngd_destroy_chn(chnId);

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

....