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
27 #include "jpege_debug.h"
28 #include "jpege_api_v2.h"
29 #include "jpege_syntax.h"
30 #include "mpp_enc_cfg_impl.h"
31 #include "mpp_bitwrite.h"
32
33 typedef struct {
34 MppEncCfgSet *cfg;
35 JpegeSyntax syntax;
36 } JpegeCtx;
37
38 #define QUANTIZE_TABLE_SIZE 64
39
40 /*
41 * from RFC435 spec.
42 */
43 static const RK_U8 jpege_luma_quantizer[QUANTIZE_TABLE_SIZE] = {
44 16, 11, 10, 16, 24, 40, 51, 61,
45 12, 12, 14, 19, 26, 58, 60, 55,
46 14, 13, 16, 24, 40, 57, 69, 56,
47 14, 17, 22, 29, 51, 87, 80, 62,
48 18, 22, 37, 56, 68, 109, 103, 77,
49 24, 35, 55, 64, 81, 104, 113, 92,
50 49, 64, 78, 87, 103, 121, 120, 101,
51 72, 92, 95, 98, 112, 100, 103, 99
52 };
53
54 static const RK_U8 jpege_chroma_quantizer[QUANTIZE_TABLE_SIZE] = {
55 17, 18, 24, 47, 99, 99, 99, 99,
56 18, 21, 26, 66, 99, 99, 99, 99,
57 24, 26, 56, 99, 99, 99, 99, 99,
58 47, 66, 99, 99, 99, 99, 99, 99,
59 99, 99, 99, 99, 99, 99, 99, 99,
60 99, 99, 99, 99, 99, 99, 99, 99,
61 99, 99, 99, 99, 99, 99, 99, 99,
62 99, 99, 99, 99, 99, 99, 99, 99
63 };
64
65 RK_U32 jpege_debug = 0;
66
jpege_init_v2(void * ctx,EncImplCfg * cfg)67 static MPP_RET jpege_init_v2(void *ctx, EncImplCfg *cfg)
68 {
69 JpegeCtx *p = (JpegeCtx *)ctx;
70
71 mpp_env_get_u32("jpege_debug", &jpege_debug, 0);
72 jpege_dbg_func("enter ctx %p\n", ctx);
73
74 p->cfg = cfg->cfg;
75
76 mpp_assert(cfg->coding = MPP_VIDEO_CodingMJPEG);
77
78 {
79 /* init default rc config */
80 MppEncRcCfg *rc = &p->cfg->rc;
81 MppEncJpegCfg *jpeg_cfg = &p->cfg->codec.jpeg;
82
83 rc->fps_in_flex = 0;
84 rc->fps_in_num = 30;
85 rc->fps_in_denorm = 1;
86 rc->fps_out_flex = 0;
87 rc->fps_out_num = 30;
88 rc->fps_out_denorm = 1;
89 rc->rc_mode = MPP_ENC_RC_MODE_VBR;
90 /* init default quant */
91 jpeg_cfg->quant = 10;
92 }
93
94 jpege_dbg_func("leave ctx %p\n", ctx);
95 return MPP_OK;
96 }
97
jpege_deinit_v2(void * ctx)98 static MPP_RET jpege_deinit_v2(void *ctx)
99 {
100 JpegeCtx *p = (JpegeCtx *)ctx;
101 MppEncJpegCfg *jpeg_cfg = &p->cfg->codec.jpeg;
102
103 jpege_dbg_func("enter ctx %p\n", ctx);
104
105 MPP_FREE(jpeg_cfg->qtable_y);
106 MPP_FREE(jpeg_cfg->qtable_u);
107 MPP_FREE(jpeg_cfg->qtable_v);
108
109 jpege_dbg_func("leave ctx %p\n", ctx);
110 return MPP_OK;
111 }
112
jpege_proc_prep_cfg(MppEncPrepCfg * dst,MppEncPrepCfg * src)113 static MPP_RET jpege_proc_prep_cfg(MppEncPrepCfg *dst, MppEncPrepCfg *src)
114 {
115 MPP_RET ret = MPP_OK;
116 RK_U32 change = src->change;
117
118 mpp_assert(change);
119 if (change) {
120 MppEncPrepCfg bak = *dst;
121 RK_S32 mirroring;
122 RK_S32 rotation;
123
124 if (change & MPP_ENC_PREP_CFG_CHANGE_FORMAT)
125 dst->format = src->format;
126
127 if (change & MPP_ENC_PREP_CFG_CHANGE_ROTATION)
128 dst->rotation_ext = src->rotation_ext;
129
130 if (change & MPP_ENC_PREP_CFG_CHANGE_MIRRORING)
131 dst->mirroring_ext = src->mirroring_ext;
132
133 if (change & MPP_ENC_PREP_CFG_CHANGE_FLIP)
134 dst->flip = src->flip;
135
136 // parameter checking
137 if (dst->rotation_ext >= MPP_ENC_ROT_BUTT || dst->rotation_ext < 0 ||
138 dst->mirroring_ext < 0 || dst->flip < 0) {
139 mpp_err("invalid trans: rotation %d, mirroring %d\n", dst->rotation_ext, dst->mirroring_ext);
140 ret = MPP_ERR_VALUE;
141 }
142
143 rotation = dst->rotation_ext;
144 mirroring = dst->mirroring_ext;
145
146 if (dst->flip) {
147 mirroring = !mirroring;
148 rotation += MPP_ENC_ROT_180;
149 rotation &= MPP_ENC_ROT_270;
150 }
151
152 dst->mirroring = mirroring;
153 dst->rotation = rotation;
154
155 /* jpeg encoder do not have denoise/sharpen feature */
156
157 if ((change & MPP_ENC_PREP_CFG_CHANGE_INPUT) ||
158 (change & MPP_ENC_PREP_CFG_CHANGE_ROTATION)) {
159 if (dst->rotation == MPP_ENC_ROT_90 || dst->rotation == MPP_ENC_ROT_270) {
160 dst->width = src->height;
161 dst->height = src->width;
162 } else {
163 dst->width = src->width;
164 dst->height = src->height;
165 }
166 dst->hor_stride = src->hor_stride;
167 dst->ver_stride = src->ver_stride;
168 }
169
170 if (dst->width < 16 || dst->width > 8192) {
171 mpp_err_f("invalid width %d is not in range [16..8192]\n", dst->width);
172 ret = MPP_NOK;
173 }
174
175 if (dst->height < 16 || dst->height > 8192) {
176 mpp_err_f("invalid height %d is not in range [16..8192]\n", dst->height);
177 ret = MPP_NOK;
178 }
179
180 dst->change |= change;
181
182 // parameter checking
183 if (dst->rotation == MPP_ENC_ROT_90 || dst->rotation == MPP_ENC_ROT_270) {
184 if (dst->height > dst->hor_stride || dst->width > dst->ver_stride) {
185 mpp_err("invalid size w:h [%d:%d] stride [%d:%d]\n",
186 dst->width, dst->height, dst->hor_stride, dst->ver_stride);
187 ret = MPP_ERR_VALUE;
188 }
189 } else {
190 if (dst->width > dst->hor_stride || dst->height > dst->ver_stride) {
191 mpp_err("invalid size w:h [%d:%d] stride [%d:%d]\n",
192 dst->width, dst->height, dst->hor_stride, dst->ver_stride);
193 ret = MPP_ERR_VALUE;
194 }
195 }
196
197 if (ret) {
198 mpp_err_f("failed to accept new prep config\n");
199 *dst = bak;
200 } else {
201 jpege_dbg_ctrl("MPP_ENC_SET_PREP_CFG w:h [%d:%d] stride [%d:%d]\n",
202 dst->width, dst->height,
203 dst->hor_stride, dst->ver_stride);
204 }
205 }
206
207 return ret;
208 }
209
210 /* gen quantizer table by q_factor according to RFC2435 spec. */
jpege_gen_qt_by_qfactor(MppEncJpegCfg * cfg,RK_S32 * factor)211 static MPP_RET jpege_gen_qt_by_qfactor(MppEncJpegCfg *cfg, RK_S32 *factor)
212 {
213 MPP_RET ret = MPP_OK;
214 RK_U32 q, qfactor = *factor;
215 RK_U32 i;
216 RK_U8 *qtable_y = NULL;
217 RK_U8 *qtable_c = NULL;
218
219 if (!cfg->qtable_y)
220 cfg->qtable_y = mpp_malloc(RK_U8, QUANTIZE_TABLE_SIZE);
221 if (!cfg->qtable_u)
222 cfg->qtable_u = mpp_malloc(RK_U8, QUANTIZE_TABLE_SIZE);
223
224 if (NULL == cfg->qtable_y || NULL == cfg->qtable_u) {
225 mpp_err_f("qtable is null, malloc err");
226 return MPP_ERR_MALLOC;
227 }
228 qtable_y = cfg->qtable_y;
229 qtable_c = cfg->qtable_u;
230
231 if (qfactor < 50)
232 q = 5000 / qfactor;
233 else
234 q = 200 - (qfactor << 1);
235
236 for (i = 0; i < QUANTIZE_TABLE_SIZE; i++) {
237 RK_S16 lq = (jpege_luma_quantizer[i] * q + 50) / 100;
238 RK_S16 cq = (jpege_chroma_quantizer[i] * q + 50) / 100;
239
240 /* Limit the quantizers to 1 <= q <= 255 */
241 qtable_y[i] = MPP_CLIP3(1, 255, lq);
242 qtable_c[i] = MPP_CLIP3(1, 255, cq);
243 }
244 return ret;
245 }
246
jpege_proc_jpeg_cfg(MppEncJpegCfg * dst,MppEncJpegCfg * src,MppEncRcCfg * rc)247 static MPP_RET jpege_proc_jpeg_cfg(MppEncJpegCfg *dst, MppEncJpegCfg *src, MppEncRcCfg *rc)
248 {
249 MPP_RET ret = MPP_OK;
250 RK_U32 change = src->change;
251
252 if (change) {
253 MppEncJpegCfg bak = *dst;
254
255 if (change & MPP_ENC_JPEG_CFG_CHANGE_QP) {
256 dst->quant = src->quant;
257 if (dst->quant < 0 || dst->quant > 10) {
258 mpp_err_f("invalid quality level %d is not in range [0..10] set to default 8\n");
259 dst->quant = 8;
260 }
261
262 if (rc->rc_mode != MPP_ENC_RC_MODE_FIXQP) {
263 mpp_log("setup quant %d change mode %s fixqp", dst->quant,
264 strof_rc_mode(rc->rc_mode));
265 rc->rc_mode = MPP_ENC_RC_MODE_FIXQP;
266 }
267 } else if (change & MPP_ENC_JPEG_CFG_CHANGE_QFACTOR) {
268 if (src->q_factor < 1 || src->q_factor > 99) {
269 mpp_err_f("q_factor out of range, default set 80\n");
270 src->q_factor = 80;
271 }
272 if (dst->q_factor != src->q_factor)
273 ret = jpege_gen_qt_by_qfactor(dst, &src->q_factor);
274
275 dst->q_factor = src->q_factor;
276 if (src->qf_min < 1 || src->qf_min > 99) {
277 mpp_err_f("qf_min out of range, default set 1\n");
278 src->qf_min = 1;
279 }
280 dst->qf_min = src->qf_min;
281 if (src->qf_max < 1 || src->qf_max > 99) {
282 mpp_err_f("qf_max out of range, default set 99\n");
283 src->qf_max = 99;
284 }
285 dst->qf_max = src->qf_max;
286 jpege_dbg_input("q_factor %d, qf_min %d, qf_max %d\n",
287 dst->q_factor, dst->qf_min, dst->qf_max);
288 } else if (change & MPP_ENC_JPEG_CFG_CHANGE_QTABLE) {
289 if (src->qtable_y && src->qtable_u && src->qtable_v) {
290 if (NULL == dst->qtable_y)
291 dst->qtable_y = mpp_malloc(RK_U8, QUANTIZE_TABLE_SIZE);
292 if (NULL == dst->qtable_u)
293 dst->qtable_u = mpp_malloc(RK_U8, QUANTIZE_TABLE_SIZE);
294
295 if (NULL == dst->qtable_y || NULL == dst->qtable_u) {
296 mpp_err_f("qtable is null, malloc err\n");
297 return MPP_ERR_MALLOC;
298 }
299 /* check table value */
300 if (src->qtable_u != src->qtable_v) {
301 RK_U32 i;
302
303 for (i = 0; i < QUANTIZE_TABLE_SIZE; i++) {
304 if (src->qtable_u[i] != src->qtable_v[i]) {
305 RK_U32 j;
306
307 jpege_dbg_input("qtable_u and qtable_v are different, use qtable_u\n");
308 for (j = 0; j < QUANTIZE_TABLE_SIZE; j++)
309 jpege_dbg_input("qtable_u[%d] %d qtable_v[%d] %d\n",
310 j, src->qtable_u[j], j, src->qtable_v[j]);
311 break;
312 }
313 }
314 }
315 /* default use one chroma qtable, select qtable_u */
316 memcpy(dst->qtable_y, src->qtable_y, QUANTIZE_TABLE_SIZE);
317 memcpy(dst->qtable_u, src->qtable_u, QUANTIZE_TABLE_SIZE);
318
319 if (rc->rc_mode != MPP_ENC_RC_MODE_FIXQP) {
320 mpp_log("setup qtable will change mode %s fixqp",
321 strof_rc_mode(rc->rc_mode));
322 rc->rc_mode = MPP_ENC_RC_MODE_FIXQP;
323 }
324 } else {
325 mpp_err_f("invalid qtable y %p u %p v %p\n",
326 src->qtable_y, src->qtable_u, src->qtable_v);
327 ret = MPP_ERR_NULL_PTR;
328 }
329 }
330
331 if (ret) {
332 mpp_err_f("failed to accept new rc config\n");
333 *dst = bak;
334 } else {
335 jpege_dbg_ctrl("MPP_ENC_SET_CODEC_CFG change 0x%x jpeg quant %d q_factor %d\n",
336 change, dst->quant, dst->q_factor);
337 dst->change = src->change;
338 }
339
340 dst->change = src->change;
341 }
342
343 return ret;
344 }
345
jpege_proc_split_cfg(MppEncSliceSplit * dst,MppEncSliceSplit * src)346 static MPP_RET jpege_proc_split_cfg(MppEncSliceSplit *dst, MppEncSliceSplit *src)
347 {
348 MPP_RET ret = MPP_OK;
349 RK_U32 change = src->change;
350
351 if (change & MPP_ENC_SPLIT_CFG_CHANGE_MODE) {
352 dst->split_mode = src->split_mode;
353 dst->split_arg = src->split_arg;
354 }
355
356 if (change & MPP_ENC_SPLIT_CFG_CHANGE_ARG)
357 dst->split_arg = src->split_arg;
358
359 dst->change |= change;
360
361 return ret;
362 }
363
jpege_proc_cfg(void * ctx,MpiCmd cmd,void * param)364 static MPP_RET jpege_proc_cfg(void *ctx, MpiCmd cmd, void *param)
365 {
366 JpegeCtx *p = (JpegeCtx *)ctx;
367 MppEncCfgSet *cfg = p->cfg;
368 MPP_RET ret = MPP_OK;
369
370 jpege_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param);
371
372 switch (cmd) {
373 case MPP_ENC_SET_CFG : {
374 MppEncCfgImpl *impl = (MppEncCfgImpl *)param;
375 MppEncCfgSet *src = &impl->cfg;
376
377 if (src->prep.change) {
378 ret |= jpege_proc_prep_cfg(&cfg->prep, &src->prep);
379 src->prep.change = 0;
380 }
381 if (src->codec.jpeg.change) {
382 ret |= jpege_proc_jpeg_cfg(&cfg->codec.jpeg, &src->codec.jpeg, &cfg->rc);
383 src->codec.jpeg.change = 0;
384 }
385 if (src->split.change) {
386 ret |= jpege_proc_split_cfg(&cfg->split, &src->split);
387 src->split.change = 0;
388 }
389 } break;
390 case MPP_ENC_SET_PREP_CFG : {
391 ret = jpege_proc_prep_cfg(&cfg->prep, param);
392 } break;
393 case MPP_ENC_SET_CODEC_CFG : {
394 MppEncCodecCfg *codec = (MppEncCodecCfg *)param;
395 ret = jpege_proc_jpeg_cfg(&cfg->codec.jpeg, &codec->jpeg, &cfg->rc);
396 } break;
397 case MPP_ENC_SET_IDR_FRAME :
398 case MPP_ENC_SET_OSD_PLT_CFG :
399 case MPP_ENC_SET_OSD_DATA_CFG :
400 case MPP_ENC_GET_SEI_DATA :
401 case MPP_ENC_SET_SEI_CFG : {
402 } break;
403 default:
404 mpp_err_f("No correspond cmd(%08x) found, and can not config!", cmd);
405 ret = MPP_NOK;
406 break;
407 }
408
409 jpege_dbg_func("leave ret %d\n", ret);
410 return ret;
411 }
412
jpege_start(void * ctx,HalEncTask * task)413 static MPP_RET jpege_start(void *ctx, HalEncTask *task)
414 {
415 JpegeCtx *p = (JpegeCtx *)ctx;
416 JpegeSyntax syntax = p->syntax;
417 MppPacket pkt = task->packet;
418 RK_U8 *ptr = mpp_packet_get_pos(pkt);
419 size_t buf_size = mpp_packet_get_size(pkt);
420 RK_S32 size = 0;
421 MppWriteCtx bit_ctx;
422 MppWriteCtx *bits = &bit_ctx;
423
424 mpp_writer_init(bits, ptr, buf_size);
425
426 /* add SOI and APP0 data */
427 /* SOI */
428 mpp_writer_put_raw_bits(bits, 0xFFD8, 16);
429 /* APP0 */
430 mpp_writer_put_raw_bits(bits, 0xFFE0, 16);
431 /* length */
432 mpp_writer_put_raw_bits(bits, 0x0010, 16);
433 /* "JFIF" ID */
434 /* Ident1 */
435 mpp_writer_put_raw_bits(bits, 0x4A46, 16);
436 /* Ident2 */
437 mpp_writer_put_raw_bits(bits, 0x4946, 16);
438 /* Ident3 */
439 mpp_writer_put_raw_bits(bits, 0x00, 8);
440 /* Version */
441 mpp_writer_put_raw_bits(bits, 0x0102, 16);
442
443 if (syntax.density_x && syntax.density_y) {
444 /* Units */
445 mpp_writer_put_raw_bits(bits, syntax.units_type, 8);
446 /* Xdensity */
447 mpp_writer_put_raw_bits(bits, syntax.density_x, 16);
448 /* Ydensity */
449 mpp_writer_put_raw_bits(bits, syntax.density_y, 16);
450 } else {
451 /* Units */
452 mpp_writer_put_raw_bits(bits, 0, 8);
453 /* Xdensity */
454 mpp_writer_put_raw_bits(bits, 0, 8);
455 mpp_writer_put_raw_bits(bits, 1, 8);
456 /* Ydensity */
457 mpp_writer_put_raw_bits(bits, 1, 16);
458 }
459 /* XThumbnail */
460 mpp_writer_put_raw_bits(bits, 0x00, 8);
461 /* YThumbnail */
462 mpp_writer_put_raw_bits(bits, 0x00, 8);
463 /* Do NOT write thumbnail */
464 size = mpp_writer_bytes(bits);
465 mpp_packet_set_length(pkt, size);
466 task->length += size;
467
468 return MPP_OK;
469 }
470
jpege_proc_hal(void * ctx,HalEncTask * task)471 static MPP_RET jpege_proc_hal(void *ctx, HalEncTask *task)
472 {
473 JpegeCtx *p = (JpegeCtx *)ctx;
474 MppFrame frame = task->frame;
475 JpegeSyntax *syntax = &p->syntax;
476 MppEncCfgSet *cfg = p->cfg;
477 MppEncPrepCfg *prep = &cfg->prep;
478 MppEncCodecCfg *codec = &cfg->codec;
479 MppEncSliceSplit *split = &cfg->split;
480
481 jpege_dbg_func("enter ctx %p\n", ctx);
482
483 syntax->width = prep->width;
484 syntax->height = prep->height;
485 syntax->hor_stride = prep->hor_stride;
486 syntax->ver_stride = prep->ver_stride;
487 syntax->mcu_w = MPP_ALIGN(prep->width, 16) / 16;
488 syntax->mcu_h = MPP_ALIGN(prep->height, 16) / 16;
489 syntax->format = prep->format;
490 syntax->color = prep->color;
491 syntax->rotation = prep->rotation;
492 syntax->mirroring = prep->mirroring;
493 syntax->offset_x = mpp_frame_get_offset_x(frame);
494 syntax->offset_y = mpp_frame_get_offset_y(frame);
495 syntax->quality = codec->jpeg.quant;
496 syntax->q_factor = codec->jpeg.q_factor;
497 syntax->qf_min = codec->jpeg.qf_min;
498 syntax->qf_max = codec->jpeg.qf_max;
499 syntax->qtable_y = codec->jpeg.qtable_y;
500 syntax->qtable_c = codec->jpeg.qtable_u;
501 syntax->part_rows = 0;
502 syntax->restart_ri = 0;
503 syntax->low_delay = 0;
504
505 if (split->split_mode) {
506 RK_U32 mb_h = MPP_ALIGN(prep->height, 16) / 16;
507 RK_U32 part_rows = 0;
508
509 if (split->split_mode == MPP_ENC_SPLIT_BY_CTU) {
510 RK_U32 part_mbs = split->split_arg;
511 RK_U32 mb_w = MPP_ALIGN(prep->width, 16) / 16;
512 RK_U32 mb_all = mb_w * mb_h;
513
514 if (part_mbs > 0 && part_mbs <= mb_all) {
515 part_rows = (part_mbs + mb_w - 1) / mb_w;
516 if (part_rows >= mb_h)
517 part_rows = 0;
518 } else {
519 mpp_err_f("warning: invalid split arg %d > max %d\n",
520 part_mbs, mb_all);
521 }
522 } else {
523 mpp_err_f("warning: only mcu split is supported\n");
524 }
525
526 if (part_rows) {
527 syntax->part_rows = part_rows;
528 syntax->restart_ri = syntax->mcu_w * part_rows;
529 syntax->low_delay = cfg->base.low_delay && part_rows;
530 jpege_dbg_func("Split by CTU, part_rows %d, restart_ri %d",
531 syntax->part_rows, syntax->restart_ri);
532 }
533 }
534
535 task->valid = 1;
536 task->syntax.data = syntax;
537 task->syntax.number = 1;
538
539 jpege_dbg_func("leave ctx %p\n", ctx);
540 return MPP_OK;
541 }
542
jpege_add_Prefix(MppPacket pkt,RK_S32 * len,RK_U8 uuid[16],const void * data,RK_S32 size)543 static MPP_RET jpege_add_Prefix(MppPacket pkt, RK_S32 *len, RK_U8 uuid[16],
544 const void *data, RK_S32 size)
545 {
546 RK_U8 *ptr = mpp_packet_get_pos(pkt);
547 size_t length = mpp_packet_get_length(pkt);
548 size_t buf_size = mpp_packet_get_size(pkt);
549 MppWriteCtx bit_ctx;
550 MppWriteCtx *bits = &bit_ctx;
551 const RK_U8 *user_data = data;
552 RK_S32 i = 0, app_size = 0;
553
554 mpp_writer_init(bits, ptr + length, buf_size - length);
555
556 if ((size > 8) && user_data[0] == 0xFF && user_data[1] == 0xE1 &&
557 user_data[4] == 0x45 && user_data[5] == 0x78 &&
558 user_data[6] == 0x69 && user_data[7] == 0x66) {
559 jpege_dbg_func("write EXIF data, total length %d\n", size);
560 } else if ((size > 8) && user_data[0] == 0xFF && user_data[1] == 0xE2 &&
561 user_data[4] == 0x4D && user_data[5] == 0x50 &&
562 user_data[6] == 0x46 && user_data[7] == 0x00) {
563 jpege_dbg_func("write MPF data, total length %d\n", size);
564 } else {
565 /* add user data to APP7 */
566 mpp_writer_put_raw_bits(bits, 0xFFE7, 16);
567 /* length */
568 mpp_writer_put_raw_bits(bits, size + 2, 16);
569 }
570
571 /* data */
572 for (i = 0; i < size; i++)
573 mpp_writer_put_raw_bits(bits, user_data[i], 8);
574
575 app_size = mpp_writer_bytes(bits);
576 *len = app_size;
577 length += app_size;
578 mpp_packet_set_length(pkt, length);
579 (void)uuid;
580 return MPP_OK;
581 }
582
583 const EncImplApi api_jpege = {
584 .name = "jpege_control",
585 .coding = MPP_VIDEO_CodingMJPEG,
586 .ctx_size = sizeof(JpegeCtx),
587 .flag = 0,
588 .init = jpege_init_v2,
589 .deinit = jpege_deinit_v2,
590 .proc_cfg = jpege_proc_cfg,
591 .gen_hdr = NULL,
592 .start = jpege_start,
593 .proc_dpb = NULL,
594 .proc_hal = jpege_proc_hal,
595 .add_prefix = jpege_add_Prefix,
596 .sw_enc = NULL,
597 };
598