JPEGD
This section describes the API call sequence of JPEGD, and sample code is also provided to help you better understand the process.
The JPEG decoder (JPEGD) can decode .jpg, .jpeg, .JPG, and .JPEG images into YUV images. For details about the JPEGD functions and restrictions, see DVPP Media Acceleration Library.
API Call Sequence
The current system supports .jpg, .jpeg, .JPG, and .JPEG image decoding. Different source image encoding formats lead to different output formats. The key APIs are described as follows:
- Call aclInit to initialize the system.
- Call aclrtSetDevice to specify the compute device.
- Call aclrtCreateStream to create a stream.
- Call acldvppCreateChannel to create an image processing channel.
Before creating a channel, call acldvppCreateChannelDesc to create a channel description.
- Before JPEG decoding, call acldvppMalloc to allocate device memory as input and output buffers.
Before allocating output buffer, call acldvppJpegPredictDecSize to predict the required output allocation size based on the JPEG image size.
The actual size may be different from the size predicated by using the acldvppJpegPredictDecSize API. To obtain the actual output allocation size, call acldvppGetPicDescSize of type acldvppPicDesc.
- Call acldvppJpegDecodeAsync to run asynchronous decoding.
Call aclrtSynchronizeStream to wait for the stream tasks to complete.
- After the decoding is complete, call acldvppFree to free the input and output buffers in a timely manner.
- Call acldvppDestroyChannel to destroy the image processing channel.
After destroying the channel, call acldvppDestroyChannelDesc to destroy the channel description.
- Call aclrtDestroyStream to destroy a stream.
- Call aclrtResetDevice to reset the device and free the resources on the device.
- 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 snippet of key steps for JPEGD image decoding. 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_jpeg_resnet50_imagenet_classification 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 |
// 1. Create description of the data processing channel. dvppChannelDesc_ is of type acldvppChannelDesc. dvppChannelDesc_ = acldvppCreateChannelDesc(); // 2. Create an image data processing channel. aclError ret = acldvppCreateChannel(dvppChannelDesc_); // 3. Allocate input buffer (run mode specific). // Call aclrtGetRunMode to obtain the run mode of the software stack. If ACL_DEVICE is returned, allocate and use the device buffer. If ACL_HOST is returned, transfer the input image data to the device by using the aclrtMemcpy call. After the data transfer is complete, the buffer needs to be freed in a timely manner. aclrtRunMode runMode; ret = aclrtGetRunMode(&runMode); if(runMode == ACL_HOST){ // Allocate the host buffer inputHostBuff and read the input image to this address. inDevBufferSize is the size of the read image. void* inputHostBuff = nullptr; inputHostBuff = malloc(inDevBufferSize); // Load the input image into the buffer. The ReadPicFile function is defined by the user. ReadPicFile(picName, inputHostBuff, inDevBufferSize); // Allocate the device buffer inDevBuffer_. ret = acldvppMalloc(&inDevBuffer_, inDevBufferSize); // Transfer the input image data to the device by using the aclrtMemcpy call. ret = aclrtMemcpy(inDevBuffer_, inDevBufferSize, inputHostBuff, inDevBufferSize, ACL_MEMCPY_HOST_TO_DEVICE); } else { // Allocate input buffer inDevBuffer_ on the device. ret = acldvppMalloc(&inDevBuffer_, inBufferSize); // Load the input image into the buffer. The ReadPicFile function is defined by the user. ReadPicFile(picName, inDevBuffer_, inBufferSize); } // 4. Allocate decoding output buffer decodeOutDevBuffer_. // Predict the buffer size required for the JPEGD result. uint32_t decodeOutBufferSize = 0; ret = acldvppJpegPredictDecSize(inputHostBuff, inDevBufferSize, PIXEL_FORMAT_YVU_SEMIPLANAR_420, &decodeOutBufferSize); ret = acldvppMalloc(&decodeOutDevBuffer_, decodeOutBufferSize); // Free the buffer in a timely manner. free(inputHostBuff); // 5. Create the description of the decoded image and set the attribute values. // decodeOutputDesc is of type acldvppPicDesc. decodeOutputDesc_ = acldvppCreatePicDesc(); acldvppSetPicDescData(decodeOutputDesc_, decodeOutDevBuffer_); acldvppSetPicDescFormat(decodeOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); acldvppSetPicDescWidth(decodeOutputDesc_, inputWidth_); acldvppSetPicDescHeight(decodeOutputDesc_, inputHeight_); acldvppSetPicDescWidthStride(decodeOutputDesc_, decodeOutWidthStride); acldvppSetPicDescHeightStride(decodeOutputDesc_, decodeOutHeightStride); acldvppSetPicDescSize(decodeOutputDesc_, decodeOutBufferSize); // 6. Perform asynchronous decoding and call aclrtSynchronizeStream to wait for the stream tasks to complete. ret = acldvppJpegDecodeAsync(dvppChannelDesc_, inDevBuffer_, inDevBufferSize, decodeOutputDesc_, stream_); ret = aclrtSynchronizeStream(stream_); // 7. Destroy the allocations, including the description of the output image, output buffer, channel description, and channel. acldvppDestroyPicDesc(decodeOutputDesc_); if(runMode == ACL_HOST){ // In this mode, the processing result is on the device. Therefore, you need to call the memory copy API to transfer the result data, and then free the device buffer. // Allocate host buffer vpcOutHostBuffer. void* vpcOutHostBuffer = nullptr; vpcOutHostBuffer = malloc(decodeOutBufferSize); // Transfer the processing result of the device to the host by using the aclrtMemcpy call. ret = aclrtMemcpy(vpcOutHostBuffer, decodeOutBufferSize, decodeOutDevBuffer_, decodeOutBufferSize, ACL_MEMCPY_DEVICE_TO_HOST); // Free the input and output buffer on the device. (void)acldvppFree(inDevBuffer_); (void)acldvppFree(decodeOutDevBuffer_); // Free the buffer after the data is used. free(vpcOutHostBuffer); } else { // The process is running on the device, and the processing result is also on the device. Free the device buffer when the data is no longer needed. (void)acldvppFree(inDevBuffer_); (void)acldvppFree(decodeOutDevBuffer_); } acldvppDestroyChannel(dvppChannelDesc_); (void)acldvppDestroyChannelDesc(dvppChannelDesc_); dvppChannelDesc_ = nullptr; .... |