1 /*
2 * Copyright 2015 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define MODULE_TAG "jpege_api_v2"
18
19 #include <string.h>
20
21 #include "mpp_err.h"
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 #include "mpp_common.h"
25 #include "mpp_2str.h"
26 #include "mpp_enc_cfg.h"
27 #include "mpp_bitwrite.h"
28 #include "mpp_soc.h"
29
30 #include "jpege_debug.h"
31 #include "jpege_api_v2.h"
32 #include "jpege_syntax.h"
33
34 typedef struct {
35 MppEncCfgSet *cfg;
36 JpegeSyntax syntax;
37 } JpegeCtx;
38
39 /*
40 * from RFC435 spec.
41 */
42
43 RK_U32 jpege_debug = 0;
44
jpege_init_v2(void * ctx,EncImplCfg * cfg)45 static MPP_RET jpege_init_v2(void *ctx, EncImplCfg *cfg)
46 {
47 JpegeCtx *p = (JpegeCtx *)ctx;
48
49 mpp_env_get_u32("jpege_debug", &jpege_debug, 0);
50 jpege_dbg_func("enter ctx %p\n", ctx);
51
52 p->cfg = cfg->cfg;
53
54 mpp_assert(cfg->coding = MPP_VIDEO_CodingMJPEG);
55
56 {
57 /* init default rc config */
58 MppEncRcCfg *rc = &p->cfg->rc;
59 MppEncJpegCfg *jpeg_cfg = &p->cfg->jpeg;
60
61 rc->fps_in_flex = 0;
62 rc->fps_in_num = 30;
63 rc->fps_in_denom = 1;
64 rc->fps_out_flex = 0;
65 rc->fps_out_num = 30;
66 rc->fps_out_denom = 1;
67 rc->rc_mode = MPP_ENC_RC_MODE_FIXQP;
68
69 /* set quant to invalid value */
70 jpeg_cfg->quant = -1;
71 jpeg_cfg->quant_ext = -1;
72 }
73
74 jpege_dbg_func("leave ctx %p\n", ctx);
75 return MPP_OK;
76 }
77
jpege_deinit_v2(void * ctx)78 static MPP_RET jpege_deinit_v2(void *ctx)
79 {
80 jpege_dbg_func("enter ctx %p\n", ctx);
81
82 jpege_dbg_func("leave ctx %p\n", ctx);
83 return MPP_OK;
84 }
85
jpege_proc_cfg(void * ctx,MpiCmd cmd,void * param)86 static MPP_RET jpege_proc_cfg(void *ctx, MpiCmd cmd, void *param)
87 {
88 MPP_RET ret = MPP_OK;
89
90 jpege_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param);
91
92 switch (cmd) {
93 case MPP_ENC_SET_CFG :
94 case MPP_ENC_SET_IDR_FRAME :
95 case MPP_ENC_SET_OSD_PLT_CFG :
96 case MPP_ENC_SET_OSD_DATA_CFG :
97 case MPP_ENC_GET_SEI_DATA :
98 case MPP_ENC_SET_SEI_CFG : {
99 } break;
100 default:
101 mpp_err_f("No correspond cmd(%08x) found, and can not config!", cmd);
102 ret = MPP_NOK;
103 break;
104 }
105
106 jpege_dbg_func("leave ret %d\n", ret);
107 return ret;
108 }
109
jpege_start(void * ctx,HalEncTask * task)110 static MPP_RET jpege_start(void *ctx, HalEncTask *task)
111 {
112 JpegeCtx *p = (JpegeCtx *)ctx;
113 JpegeSyntax syntax = p->syntax;
114 MppPacket pkt = task->packet;
115 RK_U8 *ptr = mpp_packet_get_pos(pkt);
116 size_t buf_size = mpp_packet_get_size(pkt);
117 RK_S32 size = 0;
118 MppWriteCtx bit_ctx;
119 MppWriteCtx *bits = &bit_ctx;
120
121 mpp_writer_init(bits, ptr, buf_size);
122
123 /* add SOI and APP0 data */
124 /* SOI */
125 mpp_writer_put_raw_bits(bits, 0xFFD8, 16);
126 /* APP0 */
127 mpp_writer_put_raw_bits(bits, 0xFFE0, 16);
128 /* length */
129 mpp_writer_put_raw_bits(bits, 0x0010, 16);
130 /* "JFIF" ID */
131 /* Ident1 */
132 mpp_writer_put_raw_bits(bits, 0x4A46, 16);
133 /* Ident2 */
134 mpp_writer_put_raw_bits(bits, 0x4946, 16);
135 /* Ident3 */
136 mpp_writer_put_raw_bits(bits, 0x00, 8);
137 /* Version */
138 mpp_writer_put_raw_bits(bits, 0x0102, 16);
139
140 if (syntax.density_x && syntax.density_y) {
141 /* Units */
142 mpp_writer_put_raw_bits(bits, syntax.units_type, 8);
143 /* Xdensity */
144 mpp_writer_put_raw_bits(bits, syntax.density_x, 16);
145 /* Ydensity */
146 mpp_writer_put_raw_bits(bits, syntax.density_y, 16);
147 } else {
148 /* Units */
149 mpp_writer_put_raw_bits(bits, 0, 8);
150 /* Xdensity */
151 mpp_writer_put_raw_bits(bits, 0, 8);
152 mpp_writer_put_raw_bits(bits, 1, 8);
153 /* Ydensity */
154 mpp_writer_put_raw_bits(bits, 1, 16);
155 }
156 /* XThumbnail */
157 mpp_writer_put_raw_bits(bits, 0x00, 8);
158 /* YThumbnail */
159 mpp_writer_put_raw_bits(bits, 0x00, 8);
160 /* Do NOT write thumbnail */
161 size = mpp_writer_bytes(bits);
162 mpp_packet_set_length(pkt, size);
163 task->length += size;
164
165 return MPP_OK;
166 }
167
init_jpeg_component_info(JpegeSyntax * syntax)168 static MPP_RET init_jpeg_component_info(JpegeSyntax *syntax)
169 {
170 MPP_RET ret = MPP_OK;
171 JPEGCompInfo *comp_info = (JPEGCompInfo *)syntax->comp_info;
172
173 jpege_dbg_input("Chroma format %d\n", syntax->format_out);
174
175 if (syntax->format_out == MPP_CHROMA_UNSPECIFIED)
176 syntax->format_out = MPP_CHROMA_420;
177
178 memset(comp_info, 0, sizeof(JPEGCompInfo) * MAX_NUMBER_OF_COMPONENTS);
179
180 switch (syntax->format_out) {
181 case MPP_CHROMA_400:
182 syntax->nb_components = 1;
183 comp_info[0].val = 1 | 1 << 8 | 1 << 16;
184 break;
185 case MPP_CHROMA_420:
186 syntax->nb_components = 3;
187 comp_info[0].val = 1 | 2 << 8 | 2 << 16;
188 comp_info[1].val = 2 | 1 << 8 | 1 << 16 | 1 << 24;
189 comp_info[2].val = 3 | 1 << 8 | 1 << 16 | 1 << 24;
190 break;
191 case MPP_CHROMA_422:
192 syntax->nb_components = 3;
193 comp_info[0].val = 1 | 2 << 8 | 1 << 16;
194 comp_info[1].val = 2 | 1 << 8 | 1 << 16 | 1 << 24;
195 comp_info[2].val = 3 | 1 << 8 | 1 << 16 | 1 << 24;
196 break;
197 case MPP_CHROMA_444:
198 syntax->nb_components = 3;
199 comp_info[0].val = 1 | 1 << 8 | 1 << 16;
200 comp_info[1].val = 2 | 1 << 8 | 1 << 16 | 1 << 24;
201 comp_info[2].val = 3 | 1 << 8 | 1 << 16 | 1 << 24;
202 break;
203 default:
204 syntax->nb_components = 1;
205 comp_info[0].val = 1 | 1 << 8 | 1 << 16;
206 mpp_err("Unsupported chroma format %d\n", syntax->format_out);
207 ret = MPP_ERR_VALUE;
208 break;
209 }
210
211 syntax->mcu_width = comp_info[0].h_sample_factor * DCT_SIZE;
212 syntax->mcu_height = comp_info[0].v_sample_factor * DCT_SIZE;
213 syntax->mcu_hor_cnt = (syntax->width + syntax->mcu_width - 1) / syntax->mcu_width;
214 syntax->mcu_ver_cnt = (syntax->height + syntax->mcu_height - 1) / syntax->mcu_height;
215 syntax->mcu_cnt = syntax->mcu_hor_cnt * syntax->mcu_ver_cnt;
216
217 return ret;
218 }
219
jpege_proc_hal(void * ctx,HalEncTask * task)220 static MPP_RET jpege_proc_hal(void *ctx, HalEncTask *task)
221 {
222 JpegeCtx *p = (JpegeCtx *)ctx;
223 MppFrame frame = task->frame;
224 JpegeSyntax *syntax = &p->syntax;
225 MppEncCfgSet *cfg = p->cfg;
226 MppEncPrepCfg *prep = &cfg->prep;
227 MppEncJpegCfg *jpeg = &cfg->jpeg;
228 MppEncSliceSplit *split = &cfg->split;
229
230 jpege_dbg_func("enter ctx %p\n", ctx);
231
232 syntax->width = prep->width;
233 syntax->height = prep->height;
234 syntax->hor_stride = prep->hor_stride;
235 syntax->ver_stride = prep->ver_stride;
236 syntax->format = prep->format;
237 syntax->format_out = prep->format_out;
238 syntax->color = prep->color;
239 syntax->rotation = prep->rotation;
240 syntax->mirroring = prep->mirroring;
241 syntax->offset_x = mpp_frame_get_offset_x(frame);
242 syntax->offset_y = mpp_frame_get_offset_y(frame);
243 syntax->q_mode = jpeg->q_mode;
244 syntax->quant = jpeg->quant;
245 syntax->q_factor = jpeg->q_factor;
246 syntax->qf_min = jpeg->qf_min;
247 syntax->qf_max = jpeg->qf_max;
248 syntax->qtable_y = jpeg->qtable_y;
249 syntax->qtable_u = jpeg->qtable_u;
250 syntax->qtable_v = jpeg->qtable_v;
251 syntax->part_rows = 0;
252 syntax->restart_ri = 0;
253 syntax->low_delay = 0;
254
255 init_jpeg_component_info(syntax);
256
257 if (split->split_mode) {
258 RK_U32 mb_w = syntax->mcu_hor_cnt;
259 RK_U32 mb_h = syntax->mcu_ver_cnt;
260 RK_U32 part_rows = 0;
261
262 if (split->split_mode == MPP_ENC_SPLIT_BY_CTU) {
263 RK_U32 part_mbs = split->split_arg;
264
265 if (part_mbs > 0 && part_mbs <= syntax->mcu_cnt) {
266 part_rows = (part_mbs + mb_w - 1) / mb_w;
267 if (part_rows >= mb_h)
268 part_rows = 0;
269 } else {
270 mpp_err_f("warning: invalid split arg %d > max %d\n",
271 part_mbs, syntax->mcu_cnt);
272 }
273 } else {
274 mpp_err_f("warning: only mcu split is supported\n");
275 }
276
277 if (part_rows) {
278 syntax->part_rows = part_rows;
279 if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3576 && split->split_arg <= syntax->mcu_cnt)
280 syntax->restart_ri = split->split_arg;
281 else
282 syntax->restart_ri = syntax->mcu_hor_cnt * part_rows;
283 syntax->low_delay = cfg->base.low_delay && part_rows;
284 jpege_dbg_func("Split by CTU, part_rows %d, restart_ri %d",
285 syntax->part_rows, syntax->restart_ri);
286 }
287 }
288
289 task->valid = 1;
290 task->syntax.data = syntax;
291 task->syntax.number = 1;
292
293 jpege_dbg_func("leave ctx %p\n", ctx);
294 return MPP_OK;
295 }
296
jpege_add_Prefix(MppPacket pkt,RK_S32 * len,RK_U8 uuid[16],const void * data,RK_S32 size)297 static MPP_RET jpege_add_Prefix(MppPacket pkt, RK_S32 *len, RK_U8 uuid[16],
298 const void *data, RK_S32 size)
299 {
300 RK_U8 *ptr = mpp_packet_get_pos(pkt);
301 size_t length = mpp_packet_get_length(pkt);
302 size_t buf_size = mpp_packet_get_size(pkt);
303 MppWriteCtx bit_ctx;
304 MppWriteCtx *bits = &bit_ctx;
305 const RK_U8 *user_data = data;
306 RK_S32 i = 0, app_size = 0;
307
308 mpp_writer_init(bits, ptr + length, buf_size - length);
309
310 if ((size > 8) && user_data[0] == 0xFF && user_data[1] == 0xE1 &&
311 user_data[4] == 0x45 && user_data[5] == 0x78 &&
312 user_data[6] == 0x69 && user_data[7] == 0x66) {
313 jpege_dbg_func("write EXIF data, total length %d\n", size);
314 } else if ((size > 8) && user_data[0] == 0xFF && user_data[1] == 0xE2 &&
315 user_data[4] == 0x4D && user_data[5] == 0x50 &&
316 user_data[6] == 0x46 && user_data[7] == 0x00) {
317 jpege_dbg_func("write MPF data, total length %d\n", size);
318 } else {
319 /* add user data to APP7 */
320 mpp_writer_put_raw_bits(bits, 0xFFE7, 16);
321 /* length */
322 mpp_writer_put_raw_bits(bits, size + 2, 16);
323 }
324
325 /* data */
326 for (i = 0; i < size; i++)
327 mpp_writer_put_raw_bits(bits, user_data[i], 8);
328
329 app_size = mpp_writer_bytes(bits);
330 *len = app_size;
331 length += app_size;
332 mpp_packet_set_length(pkt, length);
333 (void)uuid;
334 return MPP_OK;
335 }
336
337 const EncImplApi api_jpege = {
338 .name = "jpege_control",
339 .coding = MPP_VIDEO_CodingMJPEG,
340 .ctx_size = sizeof(JpegeCtx),
341 .flag = 0,
342 .init = jpege_init_v2,
343 .deinit = jpege_deinit_v2,
344 .proc_cfg = jpege_proc_cfg,
345 .gen_hdr = NULL,
346 .start = jpege_start,
347 .proc_dpb = NULL,
348 .proc_hal = jpege_proc_hal,
349 .add_prefix = jpege_add_Prefix,
350 .sw_enc = NULL,
351 };
352