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