xref: /OK3568_Linux_fs/external/mpp/mpp/codec/enc/jpeg/jpege_api_v2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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