1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-12-15 Rbb666 the first version
9 */
10 #include <rtthread.h>
11 #include "rthw.h"
12
13 #include "drv_g2d.h"
14 #include "drv_jpeg.h"
15
16 #ifdef BSP_USING_JPEG
17
18 static rt_sem_t _SemaphoreJPEG = RT_NULL;
19 volatile static jpeg_status_t g_jpeg_status = JPEG_STATUS_NONE;
20
_WaitForCallbackTimed(uint32_t TimeOut)21 static int32_t _WaitForCallbackTimed(uint32_t TimeOut)
22 {
23 return rt_sem_take(_SemaphoreJPEG, TimeOut) ? RT_ETIMEOUT : RT_EOK;
24 }
25
_decode_read(decode_drv_t * decode,int32_t x,int32_t y,void * pInBuffer,int32_t xSize,int32_t ySize)26 static void _decode_read(decode_drv_t *decode, int32_t x, int32_t y, void *pInBuffer, int32_t xSize, int32_t ySize)
27 {
28 decode->decode_read(x, y, pInBuffer, xSize, ySize);
29 }
30
JPEG_Draw_frame(decode_drv_t * decode,void * pbuffer,int32_t x0,int32_t y0)31 int JPEG_Draw_frame(decode_drv_t *decode, void *pbuffer, int32_t x0, int32_t y0)
32 {
33 int32_t x;
34 int32_t y;
35 int32_t Error;
36 int32_t xSize;
37 int32_t ySize;
38 int32_t OutBufferSize;
39 uint32_t LinesDecoded;
40 jpeg_color_space_t ColorSpace;
41
42 void *pOutBuffer;
43 void *_aInBuffer;
44
45 Error = 0;
46 xSize = 0;
47 ySize = 0;
48 x = x0;
49 y = y0;
50
51 g_jpeg_status = JPEG_STATUS_NONE;
52
53 fsp_err_t err = FSP_SUCCESS;
54 /* Initialize JPEG Codec Driver */
55 err = R_JPEG_Open(&g_jpeg0_ctrl, &g_jpeg0_cfg);
56 /* Handle error */
57 if (FSP_SUCCESS != err)
58 {
59 /* JPEG Codec initialization failed */
60 rt_kprintf("JPEG Codec driver initialization FAILED\n");
61 }
62
63 _aInBuffer = (uint8_t *)pbuffer;
64
65 while (!(g_jpeg_status & JPEG_STATUS_ERROR))
66 {
67 /* Set in-buffer to get some information about the JPEG */
68 if (R_JPEG_InputBufferSet(&g_jpeg0_ctrl, _aInBuffer,
69 DCODE_BUFFER_SIZE) != FSP_SUCCESS)
70 {
71 Error = 2;
72 break;
73 }
74
75 /* Wait for callback */
76 if (_WaitForCallbackTimed(JPEG_TIMEOUT) == RT_ETIMEOUT)
77 {
78 Error = 3;
79 break;
80 }
81
82 if (g_jpeg_status & JPEG_STATUS_IMAGE_SIZE_READY)
83 {
84 break;
85 }
86
87 /* Move pointer to next block of input data (if needed) */
88 // _aInBuffer = (uint8_t *)((uint32_t) _aInBuffer + DCODE_BUFFER_SIZE);
89 }
90
91 if (!Error)
92 {
93 /* Get image dimensions */
94 if (R_JPEG_DecodeImageSizeGet(&g_jpeg0_ctrl, (uint16_t *) &xSize,
95 (uint16_t *) &ySize) != FSP_SUCCESS)
96 {
97 Error = 4;
98 }
99 }
100
101 if (!Error)
102 {
103 /* Get color space and check dimensions accordingly */
104 R_JPEG_DecodePixelFormatGet(&g_jpeg0_ctrl, &ColorSpace);
105 if (g_jpeg_status & JPEG_STATUS_ERROR)
106 {
107 /* Image dimensions incompatible with JPEG Codec */
108 Error = 5;
109 }
110 }
111
112 if (!Error)
113 {
114 /* Set up out buffer */
115 // xSize * 16 * 2
116 OutBufferSize = xSize * 16 * 2;
117 pOutBuffer = (void *) decode->jpeg_out_buf;
118
119 /* Set stride value */
120 if (R_JPEG_DecodeHorizontalStrideSet(&g_jpeg0_ctrl, (uint32_t) xSize) != FSP_SUCCESS)
121 {
122 Error = 6;
123 }
124 }
125
126 if (!Error)
127 {
128 /* Start decoding process by setting out-buffer */
129 if (R_JPEG_OutputBufferSet(&g_jpeg0_ctrl, pOutBuffer, (uint32_t) OutBufferSize) != FSP_SUCCESS)
130 {
131 Error = 7;
132 }
133 }
134
135 if (!Error)
136 {
137 while (!(g_jpeg_status & JPEG_STATUS_ERROR))
138 {
139 if (_WaitForCallbackTimed(JPEG_TIMEOUT) == RT_ETIMEOUT)
140 {
141 Error = 8;
142 break;
143 }
144
145 if ((g_jpeg_status & JPEG_STATUS_OUTPUT_PAUSE) || (g_jpeg_status & JPEG_STATUS_OPERATION_COMPLETE))
146 {
147 /* Draw the JPEG work buffer to the framebuffer */
148 R_JPEG_DecodeLinesDecodedGet(&g_jpeg0_ctrl, &LinesDecoded);
149
150 _decode_read(decode, x, y, (void *) pOutBuffer, xSize, (int32_t)LinesDecoded);
151
152 y = y + (int32_t)LinesDecoded;
153
154 if (!(g_jpeg_status & JPEG_STATUS_OPERATION_COMPLETE))
155 {
156 /* Set the output buffer to the next 16-line block */
157 if (R_JPEG_OutputBufferSet(&g_jpeg0_ctrl, pOutBuffer,
158 (uint32_t) OutBufferSize) != FSP_SUCCESS)
159 {
160 Error = 10;
161 break;
162 }
163 }
164 }
165
166 if (g_jpeg_status & JPEG_STATUS_INPUT_PAUSE)
167 {
168 /* Get next block of input data */
169 /* Set the new input buffer pointer */
170 if (R_JPEG_InputBufferSet(&g_jpeg0_ctrl, (void *) _aInBuffer,
171 DCODE_BUFFER_SIZE) != FSP_SUCCESS)
172 {
173 Error = 9;
174 break;
175 }
176 }
177
178 if (g_jpeg_status & JPEG_STATUS_OPERATION_COMPLETE)
179 {
180 break;
181 }
182 }
183 }
184
185 if ((g_jpeg_status & JPEG_STATUS_ERROR) && (!Error))
186 {
187 Error = 1;
188 }
189
190 R_JPEG_Close(&g_jpeg0_ctrl);
191
192 return Error;
193 }
194
rt_hw_jpeg_init(void)195 int rt_hw_jpeg_init(void)
196 {
197 _SemaphoreJPEG = rt_sem_create("jpeg_sem", 0, RT_IPC_FLAG_PRIO);
198 if (_SemaphoreJPEG == RT_NULL)
199 {
200 rt_kprintf("create jpeg decode semphr failed.\n");
201 return RT_ERROR;
202 }
203
204 return RT_EOK;
205 }
206 INIT_DEVICE_EXPORT(rt_hw_jpeg_init);
207
208 /*******************************************************************************************************************//**
209 * @brief Decode callback function.
210 * @param[in] p_args
211 * @retval None
212 **********************************************************************************************************************/
decode_callback(jpeg_callback_args_t * p_args)213 void decode_callback(jpeg_callback_args_t *p_args)
214 {
215 rt_interrupt_enter();
216
217 g_jpeg_status = p_args->status;
218
219 rt_sem_release(_SemaphoreJPEG);
220
221 rt_interrupt_leave();
222 }
223 #endif
224