JPEGE

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

The JPEG encoder (JPEGE) encodes YUV images into .jpg images. For details about the JPEGE functions and restrictions, see DVPP Media Acceleration Library.

API Call Sequence

Figure 1 Process of calling the JPEGE image encoding function
The current system supports encoding YUV images into JPEG images. The key APIs are described as follows:
  1. Initialize resources.
    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_venc_create_chn to create a channel.

      After creating a channel, you can set advanced encoding parameters such as the scene mode and stream controller as required. For details, see sections from hi_mpi_venc_set_jpeg_param to hi_mpi_venc_compact_jpeg_tables.

    5. Call hi_mpi_venc_get_fd to obtain the file descriptor corresponding to the channel ID.
    6. Call hi_mpi_sys_create_epoll to create a DVPP epoll instance.

      Note: In Open Ctrl CPU form, to ensure compatibility, it is allowed to call the select or poll function of the Linux OS for an older version of an app to wait for the encoding to complete. You are advised to use the API call sequence shown in the preceding figure to ensure the evolution of later versions.

    7. Call hi_mpi_sys_ctl_epoll to add the file descriptor corresponding to the encoding channel to the epoll instance.

      Skip this step if the select or poll function is used.

  2. Encode images.
    1. Call hi_mpi_venc_start_chn to notify the channel to start encoding.
    2. Call hi_mpi_dvpp_malloc to allocate the device memory to store the input data.
    3. Start a user-mode thread and call hi_mpi_sys_wait_epoll to wait for the epoll instance to complete encoding.
    4. Call hi_mpi_venc_send_frame to feed your stream to the encoder.
    5. Once the encoding is complete, the hi_mpi_sys_wait_epoll, select, or poll function returns a value. Call hi_mpi_venc_query_status to query the encoding status and call hi_mpi_venc_get_stream to obtain the encoding result.
    6. Call hi_mpi_venc_release_stream to free the buffer in time when the encoding result is no longer needed. Otherwise, no more encoding task can be performed because the encoding buffer is used up.
    7. Call hi_mpi_dvpp_free to free the input buffer.
    8. When the source images have been completely fed, call hi_mpi_venc_stop_chn to stop the channel from receiving new images.
  3. Destroy resources.
    1. Call hi_mpi_sys_ctl_epoll to delete the encoding channel file descriptor from the epoll instance.
    2. After all encoding tasks are complete, call hi_mpi_venc_destroy_chn to destroy the encoding channel and free the memory.
    3. Call hi_mpi_sys_close_epoll to destroy the DVPP epoll instance.
    4. Call hi_mpi_sys_exit to deinitialize the media data processing system.
    5. Call aclrtResetDevice to reset the device and free the resources on the device.
    6. 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 JPEGE image encoding. It is for reference only. Do not copy, build, or run it directly. Following the API calls, add exception handling branches and specify log printing of error and information levels.

You can click jpege_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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// 1. Initialize the media data processing system.
int32_t ret = hi_mpi_sys_init();

// 2. Create a channel.
hi_venc_chn chn = 0;
hi_venc_chn_attr attr{};
attr.venc_attr.type = HI_PT_JPEG;
attr.venc_attr.profile = 0;
attr.venc_attr.max_pic_width = 128;
attr.venc_attr.max_pic_height = 128;
attr.venc_attr.pic_width = 128;
attr.venc_attr.pic_height = 128;
attr.venc_attr.buf_size = 2 * 1024 * 1024;
attr.venc_attr.is_by_frame = HI_TRUE;
attr.venc_attr.jpeg_attr.dcf_en = HI_FALSE;
attr.venc_attr.jpeg_attr.recv_mode = HI_VENC_PIC_RECV_SINGLE;
attr.venc_attr.jpeg_attr.mpf_cfg.large_thumbnail_num = 0;
ret = hi_mpi_venc_create_chn(chn, &attr);

// 3. Notify the encoder to start receiving input data.
hi_venc_start_param recv_param{};
recv_param.recv_pic_num = -1;
ret = hi_mpi_venc_start_chn(chn, &recv_param);

// 4. Send the input data.
// 4.1 Allocate input buffer.
uint8_t* inputAddr = nullptr;
int32_t inputSize = 128 * 128 * 3 / 2;
ret = hi_mpi_dvpp_malloc(0, &inputAddr, inputSize);
// Load the input data into the buffer. The function JpegeReadYuvFile is implemented by the user.
JpegeReadYuvFile(streamName, inputAddr, inputSize);

// 4.2 Send the input data and start encoding.
hi_video_frame_info frame{};
frame.mod_id = HI_ID_VENC;
frame.v_frame.width = 128;
frame.v_frame.height = 128;
frame.v_frame.field = HI_VIDEO_FIELD_FRAME;
frame.v_frame.pixel_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
frame.v_frame.video_format = HI_VIDEO_FORMAT_LINEAR;
frame.v_frame.compress_mode = HI_COMPRESS_MODE_NONE;
frame.v_frame.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
frame.v_frame.color_gamut = HI_COLOR_GAMUT_BT709;
frame.v_frame.width_stride[0] = 128;
frame.v_frame.width_stride[1] = 128;
frame.v_frame.width_stride[2] = 128;
frame.v_frame.virt_addr[0] = inputAddr;
frame.v_frame.virt_addr[1] = (hi_void *)((uintptr_t)frame.v_frame.virt_addr[0] + 128 * 128);
frame.v_frame.frame_flag = 0;
frame.v_frame.time_ref = 0;
frame.v_frame.pts = 0;
ret = hi_mpi_venc_send_frame(chn, &frame, 0);

// 5. Obtain the encoding result.
// 5.1 Create an epoll instance.
int32_t epollFd = 0;
int32_t fd = hi_mpi_venc_get_fd(chn);
ret = hi_mpi_sys_create_epoll(10, &epollFd);

hi_dvpp_epoll_event event;
event.events = HI_DVPP_EPOLL_IN;
event.data = (void*)(unsigned long)(fd);
ret = hi_mpi_sys_ctl_epoll(epollFd, HI_DVPP_EPOLL_CTL_ADD, fd, &event);

int32_t eventCount = 0;
// Before the encoding is complete, timeout occurs. The next step is not performed until the encoding is complete.
ret = hi_mpi_sys_wait_epoll(epollFd, event, 3, 1000, &eventCount);

// 5.2 Obtain the encoding result.
hi_venc_chn_status stat;
ret = hi_mpi_venc_query_status(chn, &stat);
hi_venc_stream stream;
stream.pack_cnt = stat.cur_packs;
stream.pack = new hi_venc_pack[stream.pack_cnt];
ret = hi_mpi_venc_get_stream(chn, &stream, 1000);

// 5.3 Obtain the encoded streams from the buffer to which stream.pack[0].addr points.
......

// 6. Free the input buffer and release the output streams.
ret = hi_mpi_dvpp_free(inputAddr);
ret = hi_mpi_venc_release_stream(chn, &stream);
delete[] stream.pack;

// 7. Notify the encoder to stop receiving input data.
ret = hi_mpi_venc_stop_chn(chn);
ret = hi_mpi_sys_ctl_epoll(epollFd, HI_DVPP_EPOLL_CTL_DEL, fd, NULL);
ret = hi_mpi_sys_close_epoll(epollFd);

// 8. Destroy the channel.
ret = hi_mpi_venc_destroy_chn(chn);

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

....