VENC
The video encoder (VENC) encodes YUV420SP images into H.264/H.265 video streams. For details about the VENC function, see VENC Functions and Restrictions.
This section describes the API call sequence of VENC, and sample code is also provided to help you better understand the sequence.
For the
For the
API Call Sequence
If video encoding is involved during app development, the app must contain the encoding code logic. For details about the API call sequence for encoding, see API Call Sequence. Then view the process description in this section..
- Call acl.himpi.sys_init to initialize the media data processing system.
- Call the acl.himpi.venc_create_chn function to create a channel.
After a channel is created, you can set advanced encoding parameters as required, such as the scenario mode and advanced parameters of the stream controller. For details, see the API description in acl.himpi.venc_set_jpeg_param to acl.himpi.venc_compact_jpeg_tables.
- Call acl.himpi.venc_get_fd to convert the channel ID into a file descriptor.
- Call the acl.himpi.sys_create_epoll function to create a DVPP epoll instance.
- Call the acl.himpi.sys_ctl_epoll function to add the file descriptor of the encoding channel to the epoll instance. The epoll instance processes the file descriptor.
Skip this step if the select or poll function is used.
- Call the acl.himpi.venc_start_chn function to notify the channel to start encoding.
- Call the acl.himpi.dvpp_malloc API to allocate memory for storing the input data on the device.
For the
Atlas 200I/500 A2 inference product , the acl.rt.malloc API can also be used to allocate memory.For
Atlas 200I/500 A2 inference product , the memory allocated by calling acl.himpi.dvpp_malloc is the dedicated memory for media data processing. However, the address space of the dedicated memory is limited. If you are concerned about memory planning or memory resources are limited, you are advised to call acl.rt.malloc to allocate memory. - Start a user-mode thread and call the acl.himpi.sys_wait_epoll function to wait until the encoding is complete.
- Then, you can call the acl.himpi.venc_send_frame function to send the stream to be encoded.
- Once the encoding is complete, the acl.himpi.sys_wait_epoll, select, or poll function returns. You can call the acl.himpi.venc_query_status API to query the encoding status and then call the acl.himpi.venc_get_stream API to obtain the encoding result.
- Note that you need to call the acl.himpi.venc_release_stream function to release the buffer after the encoding result data is used. Otherwise, no more encoding task can be performed because the encoding buffer is used up.
- Call acl.himpi.dvpp_free to free the input buffer.
For the
Atlas 200I/500 A2 inference product , if acl.rt.malloc is used to allocate memory, acl.rt.free must be used to free memory. - If you do not need to send images to the target channel for further encoding, you need to call the acl.himpi.venc_stop_chn function to notify the channel not to receive new input images.
- Call the acl.himpi.sys_ctl_epoll function to delete the file descriptor of the encoding channel from the epoll instance.
- After encoding is complete, you need to call acl.himpi.venc_destroy_chn to release the encoding channel and internal memory resources.
- Call the acl.himpi.sys_close_epoll function to close the DVPP epoll instance.
- Deinitialize the media data processing system by calling acl.himpi.sys_exit.
Optimization of Video Encoding Quality
When implementing the VENC function, you can set basic parameters during channel creation or set advanced parameters by calling the corresponding set API to optimize the video encoding quality. The following optimization settings are available and can be used jointly:
- Settings for H.264 monitoring with the resolution of 720p, GOP of 60, frame rate of 30 FPS, and bit rate of 1 Mbit/s: CBR mode, HI_VENC_SCENE_0, stats_time = 2, profile = 2, and macroblock-level bit rate control = disabled.
- Settings for H.265 movies with the resolution of 1080p, GOP of 30, frame rate of 25 FPS, and bit rate of 2 Mbit/s: CBR mode, HI_VENC_SCENE_1, stats_time = 1, and macroblock-level bit rate control = disabled.
You can optimize the video encoding quality using the following methods:
- Setting basic parameters for overall quality optimization
The encoding quality of videos with different resolutions is subject to the video frame rate, GOP, and bit rate. When a channel is created by calling acl.himpi.venc_create_chn, you can set the encoding profile and parameters such as the frame rate, GOP, and bit rate in CBR/VBR/AVBR/CVBR/QVBR mode for H.264/H.265 encoding to optimize the video encoding quality.
- Encoding level, which is determined by the profile attribute in the hi_venc_chn_attr ["venc_attr"] dictionary.
- Frame rate, which is determined by the src_frame_rate input frame rate and dst_frame_rate output frame rate in the hi_venc_chn_attr ["rc_attr"] dictionary.
- GOP, which is determined by the gop attribute in the hi_venc_chn_attr ["rc_attr"] dictionary.
- Bit rate, which is determined by the bit_rate, max_bit_rate, or target_bit_rate attribute in the hi_venc_chn_attr ["rc_attr"] dictionary.
Table 1 Values of the frame rate, GOP, and bit rate in typical scenarios Picture Quality/Resolution
Frame Rate (FPS)
GOP
Bit Rate (Mbit/s)
4K
3840 x 2160/4096 x 2160
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
2K
2560 x 1440
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
1080p (Blu-ray)
1920 x 1080
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
720p (HD)
1280 x 720
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
480p/D1_N (SD)
854 x 480/720 x 480
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
576p/D1 (SD)
720 x 576
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
270p (smooth)
480 x 270
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
CIF P/N
352 x 288/320 x 240
25 or 30
It is recommended that the GOP value be an integral multiple of the frame rate. For example, if the frame rate is 25, the recommended GOP value is 25 or 50.
- Setting advanced parameters for quality tuning
You can call the APIs listed in the following table to set the bit rate control mode, macroblock-level bit rate control parameters, and encoding scene mode to tune video encoding quality.
Table 2 Advanced settings Item
API
Parameter
Description
Bit rate control mode
hi_venc_chn_attr: rc_mode attribute in the ["rc_attr"] dictionary
Set this parameter to CBR if a stable bit rate or a large peak signal to noise ratio (PSNR) and qualified bit rate is required.
Set this parameter to VBR to save the bit rate and improve the subjective quality of encoding.
Set this parameter to AVBR to save the bit rate and improve the subjective quality of encoding with lots of still images in the scene.
Set this parameter to QVBR if a large PSNR is required and there is no strict requirement on the bit rate increase.
Set this parameter to CVBR to save the bit rate and improve the subjective quality of encoding when the bandwidth and storage space can also be used for optimization.
Statistical time of the bit rate control model
hi_venc_chn_attr ["rc_attr"]: stats_time attribute in the dictionary of each mode attribute value
Set this parameter to a large value in the scenario where long-term bit rate stability is required without considering short-term fluctuations, for example, DVR storage. This setting increases the threshold for re-encoding to cut the number of re-encoding times, but also increases bit rate fluctuations at the same time.
Macroblock-level bit rate control
threshold_i, threshold_p, threshold_b, direction, and row_qp_delta attributes in the hi_venc_rc_param dictionary.
Disable this function when encoding complex images with rich details, or when objective indicators such as the PSNR are concerned.
Start QP value of the first frame
In typical scenarios, if the configured bit rate is less than the reference value in Table 1 and the first frame of the encoded video is blurry, you are advised to configure the first_frame_start_qp attribute and set the parameter value to the intermediate value of [min_i_qp, max_i_qp]. For example, if [min_i_qp, max_i_qp] is [30, 40], set first_frame_start_qp to 35 and max_reencode_times to 0 to obtain better encoding quality.
Encoding scene mode
Set this parameter to HI_VENC_SCENE_0 for security scenes. Set this parameter to HI_VENC_SCENE_1 for autonomous driving, livestreaming, gaming, animations, and movies.
Sample Code
Following the API calls, add exception handling branches and specify log printing of error and information levels. The following is a code snippet of key steps only, which is not ready to use.
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# 1. Obtain the run mode of the software stack. Different run modes lead to different API call sequences (for example, whether data transfer is required). run_mode, ret = acl.rt.get_run_mode() # 2. Perform initialization. ret = acl.init() # 3. Allocate runtime resources. # 4. Initialize the media data processing system. ret = acl.himpi.sys_init() # 5. Set VENC parameters. param = {'mod_type':HI_VENC_MOD_H265} param, ret = acl.himpi.venc_get_mod_param(param) param['jpeg_mod_param']['one_stream_buf'] = 1 ret = acl.himpi.venc_set_mod_param(param) # 6. Create a channel. channel_id = 0 venc_attr = {'type': HI_VENC_MOD_H265, 'profile': 0, 'max_pic_width': 128, 'pic_width': 128, 'max_pic_height': 128, 'pic_height': 128, 'buf_size': 1024 * 1024 * 2, 'is_by_frame': 1} rc_attr = {'rc_mode':HI_VENC_RC_MODE_H265_VBR, 'h265_vbr':{'gop': 30, 'stats_time': 1, 'src_frame_rate': 30, 'dst_frame_rate': 30, 'max_bit_rate': 4000}} gop_attr = {'gop_mode':0, 'normal_p':{'ip_qp_delta':3}} attr = {'venc_attr':venc_attr, 'rc_attr':rc_attr, 'gop_attr':gop_attr} ret = acl.himpi.venc_create_chn(channel_id, attr) # 7. Notify the encoder to start receiving input data. recv_param = {'recv_pic_num':-1} ret = acl.himpi.venc_start_chn(channel_id, recv_param) # 8. Send the input data. # 8.1 Allocate the input buffer. input_size = 128 * 128 * 3 // 2 input_addr, ret = acl.himpi.dvpp_malloc(0, input_size); # If the run mode is ACL_HOST, allocate the host buffer, load the input data into the host buffer, and call acl.rt.memcpy to transfer the host data to the device. After the data transfer is complete, free the host buffer in a timely manner. In other modes, directly load the input data into the device buffer. # Directly load the input data into the device buffer. if run_mode == ACL_HOST: # Read the input image to the buffer. jpege_file = np.fromfile(jpege_file_path, dtype=np.byte) jpege_file_size = jpege_file.itemsize * jpege_file.size bytes_data = jpege_file.tobytes() jpege_file_ptr = acl.util.bytes_to_ptr(bytes_data) # Transfer data. ret = acl.rt.memcpy(input_addr, input_size, jpege_file_ptr, jpege_file_size, ACL_MEMCPY_HOST_TO_DEVICE) else: # Read the input image to the buffer. jpege_file = np.fromfile(jpege_file_path, dtype=np.byte) jpege_file_size = jpege_file.itemsize * jpege_file.size bytes_data = jpege_file.tobytes() jpege_file_ptr = acl.util.bytes_to_ptr(bytes_data) # Transfer data. ret = acl.rt.memcpy(input_addr, input_size, jpege_file_ptr, jpege_file_size, ACL_MEMCPY_DEVICE_TO_DEVICE) # 8.2 Send the input data and start encoding. v_frame = {'width': 128, 'height': 128, 'field': HI_VIDEO_FIELD_FRAME, 'pixel_format': HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420, 'video_format': HI_VIDEO_FORMAT_LINEAR, 'compress_mode': HI_COMPRESS_MODE_NONE, 'dynamic_range': HI_DYNAMIC_RANGE_SDR8, 'color_gamut': HI_COLOR_GAMUT_BT709, 'header_stride': [0, 0, 0], 'width_stride': [128, 0, 0], 'height_stride': [0, 0, 0], 'header_phys_addr': [0, 0, 0], 'phys_addr': [0, 0, 0], 'header_virt_addr': [0, 0, 0], 'virt_addr': [input_addr, 0, 0], 'time_ref': 0,'pts': cur_time} frame = {'v_frame':v_frame, 'pool_id':0, 'mod_id':HI_ID_VENC} ret = acl.himpi.venc_send_frame(channel_id, frame, 0) # 9. Obtain the encoding result. # 9.1 Handle the encoding completion event through epoll. fd = acl.himpi.venc_get_fd(channel_id) epoll_fd, ret = acl.himpi.sys_create_epoll(10) event = {'data': fd, 'events': HI_DVPP_EPOLL_IN} ret = acl.himpi.sys_ctl_epoll(epoll_fd, HI_DVPP_EPOLL_CTL_ADD, fd, event) # Before the encoding is complete, timeout occurs. The next step is not performed until the encoding is complete. events, eventCount, ret = acl.himpi.sys_wait_epoll(epoll_fd, 3, 1000); # 9.2 Obtain the encoding result. status, ret = acl.himpi.venc_query_status(channel_id) stream = {'pack_cnt': status['cur_packs']} stream, ret = acl.himpi.venc_get_stream(self.channel_id, stream, 1000) # 9.3 If the run mode is ACL_HOST and the host needs to use the encoded streams, allocate the host buffer and call acl.rt.memcpy to transfer the output streams from the device to the host. # Obtain the encoded streams. if run_mode == ACL_HOST: # Allocate the host buffer. output_buffer, ret= acl.rt.malloc_host(output_size) # Transfer data. ret = acl.rt.memcpy(output_buffer, output_size, stream['pack'][0]['addr'], output_size, ACL_MEMCPY_DEVICE_TO_HOST) # ...... # After data is used, free the buffer in a timely manner. ret = acl.rt.free_host(output_buffer) else: # You can directly use the encoded streams, which are stored in the buffer specified by stream['pack'][0]['addr']. # ...... # 10. Free the input buffer and release the output streams. ret = acl.himpi.dvpp_free(input_addr) ret = acl.himpi.venc_release_stream(channel_id, stream) # 11. Notify the encoder to stop receiving input data. ret = acl.himpi.venc_stop_chn(channel_id) ret = acl.himpi.sys_ctl_epoll(epoll_fd, HI_DVPP_EPOLL_CTL_DEL, fd, event) ret = acl.himpi.sys_close_epoll(epoll_fd) # 12. Destroy the channel. ret = acl.himpi.venc_destroy_chn(channel_id) # 13. Deinitialize the media data processing system. ret = acl.himpi.sys_exit() # 14. Deallocate runtime resources. # 15. Perform deinitialization. ret = acl.finalize() |