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 function 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.
- aclrtCreateStream: creates a stream.
- Call acldvppCreateChannel to create a channel for image data processing.
Before creating a channel, call <cf id="Bold">acldvppCreateChannelDesc</cf> to create the channel description.
- Before decoding JPEG images, call acldvppMalloc to allocate memory on the device for storing the input or output data.
Before allocating the output buffer, call acldvppJpegPredictDecSize to estimate the size of the output buffer required for the decoded JPEG image based on the buffer for storing JPEG image data.
The actual output buffer size may be different from the size estimated by calling acldvppJpegPredictDecSize. To obtain the actual output buffer size after decoding, call acldvppGetPicDescSize of the acldvppPicDesc type.
- Call the asynchronous API acldvppJpegDecodeAsync for decoding.
For asynchronous APIs, call aclrtSynchronizeStream to block program running until all tasks in the specified stream are 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 data processing channel.
After destroying the channel, call <cf id="Bold">acldvppDestroyChannelDesc</cf> to destroy the channel description.
- aclrtDestroyStream: destroys 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 example of key steps of JPEGD 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 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 the description of the image data processing channel. dvppChannelDesc_ is of the acldvppChannelDesc type. dvppChannelDesc_ = acldvppCreateChannelDesc(); // 2. Create a channel for processing image data. aclError ret = acldvppCreateChannel(dvppChannelDesc_); // 3. Allocate input buffer (differentiated by running status). // 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 the 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 block program running until all tasks in the specified stream are complete. ret = acldvppJpegDecodeAsync(dvppChannelDesc_, inDevBuffer_, inDevBufferSize, decodeOutputDesc_, stream_); ret = aclrtSynchronizeStream(stream_); // 7. After the decoding is complete, release the resources, including the description of the decoded 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; .... |