1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "kmpp"
7
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <sys/ioctl.h>
14
15 #include "rk_mpi.h"
16
17 #include "mpp_log.h"
18 #include "mpp_mem.h"
19 #include "mpp_env.h"
20 #include "mpp_time.h"
21 #include "mpp_impl.h"
22 #include "mpp_2str.h"
23 #include "mpp_debug.h"
24
25 #include "kmpp.h"
26 #include "kmpp_obj.h"
27 #include "mpp_soc.h"
28 #include "kmpp_frame.h"
29 #include "mpp_buffer_impl.h"
30 #include "mpp_frame_impl.h"
31 #include "mpp_packet_impl.h"
32 #include "kmpp_packet.h"
33 #include "mpp_vcodec_client.h"
34 #include "mpp_enc_cfg.h"
35
36 typedef struct KmppFrameInfos_t {
37 RK_U32 width;
38 RK_U32 height;
39 RK_U32 hor_stride;
40 RK_U32 ver_stride;
41 RK_U32 hor_stride_pixel;
42 RK_U32 offset_x;
43 RK_U32 offset_y;
44 RK_U32 fmt;
45 RK_U32 fd;
46 RK_U64 pts;
47 RK_S32 jpeg_chan_id;
48 void *osd_buf;
49 RK_S32 mpi_buf_id;
50 void *jpg_combo_osd_buf;
51 RK_U32 is_gray;
52 RK_U32 is_full;
53 RK_U32 phy_addr;
54 RK_U64 dts;
55 void *pp_info;
56 RK_U32 pskip_num;
57 union {
58 RK_U32 val;
59 struct {
60 RK_U32 eos : 1;
61 RK_U32 pskip : 1;
62 RK_U32 isr_request : 1;
63 };
64 };
65 } KmppFrameInfos;
66
kmpp_release_venc_packet(void * ctx,void * arg)67 static void kmpp_release_venc_packet(void *ctx, void *arg)
68 {
69 KmppPacket pkt = (KmppPacket)arg;
70
71 if (!ctx || !pkt) {
72 mpp_err_f("invalid input ctx %p pkt %p\n", ctx, pkt);
73 return;
74 }
75
76 kmpp_packet_put(pkt);
77 }
78
init(Kmpp * ctx,MppCtxType type,MppCodingType coding)79 static MPP_RET init(Kmpp *ctx, MppCtxType type, MppCodingType coding)
80 {
81 MPP_RET ret = MPP_NOK;
82 RK_U32 chan_id;
83 void *hnd;
84 RK_U32 size;
85
86 if (!ctx)
87 return MPP_ERR_VALUE;
88
89 if (mpp_check_support_format(type, coding)) {
90 mpp_err("unable to create %s %s for mpp unsupported\n",
91 strof_ctx_type(type), strof_coding_type(coding));
92 return MPP_NOK;
93 }
94
95 if (ctx->mClientFd < 0) {
96 ctx->mClientFd = mpp_vcodec_open();
97 if (ctx->mClientFd < 0) {
98 mpp_err("mpp_vcodec dev open failed\n");
99 return MPP_NOK;
100 }
101 }
102
103 hnd = kmpp_obj_to_shm(ctx->mVencInitKcfg);
104 size = kmpp_obj_to_shm_size(ctx->mVencInitKcfg);
105 kmpp_obj_get_u32(ctx->mVencInitKcfg, "chan_dup", &ctx->mChanDup);
106 kmpp_obj_set_s32(ctx->mVencInitKcfg, "chan_fd", ctx->mClientFd);
107
108 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_CREATE, 0, size, hnd);
109 if (ret) {
110 mpp_err("chan %d VCODEC_CHAN_CREATE failed\n", ctx->mChanId);
111 return ret;
112 }
113
114 if (!ctx->mChanDup) {
115 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0);
116 if (ret) {
117 mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId);
118 return ret;
119 }
120 }
121
122 if (ctx->mPacketGroup == NULL)
123 mpp_buffer_group_get_internal(&ctx->mPacketGroup, MPP_BUFFER_TYPE_ION);
124
125 kmpp_obj_get_u32(ctx->mVencInitKcfg, "chan_id", &chan_id);
126 mpp_log("client %d open chan_id %d ok", ctx->mClientFd, chan_id);
127 ctx->mInitDone = 1;
128 ctx->mChanId = chan_id;
129 ctx->mType = type;
130 ctx->mOutputTimeout = MPP_POLL_BLOCK;
131 ctx->mTimeout.tv_sec = 2;
132 ctx->mTimeout.tv_usec = 100000;
133
134 return ret;
135 }
136
open_client(Kmpp * ctx)137 static MPP_RET open_client(Kmpp *ctx)
138 {
139 if (!ctx)
140 return MPP_ERR_VALUE;
141
142 ctx->mClientFd = mpp_vcodec_open();
143 if (ctx->mClientFd < 0) {
144 mpp_err("mpp_vcodec dev open failed\n");
145 return MPP_NOK;
146 }
147 return MPP_OK;
148 }
149
clear(Kmpp * ctx)150 static void clear(Kmpp *ctx)
151 {
152 if (!ctx)
153 return;
154
155 if (!ctx->mChanDup) {
156 MPP_RET ret;
157
158 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_DESTROY, 0, 0, 0);
159 if (ret)
160 mpp_err("chan %d VCODEC_CHAN_DESTROY failed\n", ctx->mChanId);
161 }
162
163 if (ctx->mClientFd >= 0)
164 mpp_vcodec_close(ctx->mClientFd);
165 ctx->mClientFd = -1;
166
167 if (ctx->mPacketGroup) {
168 mpp_buffer_group_put(ctx->mPacketGroup);
169 ctx->mPacketGroup = NULL;
170 }
171
172 if (ctx->mKframe) {
173 kmpp_frame_put(ctx->mKframe);
174 ctx->mKframe = NULL;
175 }
176 }
177
start(Kmpp * ctx)178 static MPP_RET start(Kmpp *ctx)
179 {
180 MPP_RET ret = MPP_OK;
181
182 if (!ctx)
183 return MPP_ERR_VALUE;
184
185 if (ctx->mChanDup)
186 return MPP_OK;
187
188 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0);
189 if (ret)
190 mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId);
191
192 return ret;
193 }
194
stop(Kmpp * ctx)195 static MPP_RET stop(Kmpp *ctx)
196 {
197 MPP_RET ret = MPP_OK;
198
199 if (!ctx)
200 return MPP_ERR_VALUE;
201
202 if (ctx->mChanDup)
203 return MPP_OK;
204
205 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0);
206 if (ret)
207 mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId);
208
209 return ret;
210 }
211
mpp_pause(Kmpp * ctx)212 static MPP_RET mpp_pause(Kmpp *ctx)
213 {
214 MPP_RET ret = MPP_OK;
215
216 if (!ctx)
217 return MPP_ERR_VALUE;
218
219 if (ctx->mChanDup)
220 return MPP_OK;
221
222 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_PAUSE, 0, 0, 0);
223 if (ret)
224 mpp_err("chan %d VCODEC_CHAN_PAUSE failed\n", ctx->mChanId);
225
226 return ret;
227 }
228
resume(Kmpp * ctx)229 static MPP_RET resume(Kmpp *ctx)
230 {
231 MPP_RET ret = MPP_OK;
232
233 if (!ctx)
234 return MPP_ERR_VALUE;
235
236 if (ctx->mChanDup)
237 return MPP_OK;
238
239 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_RESUME, 0, 0, 0);
240 if (ret)
241 mpp_err("chan %d VCODEC_CHAN_RESUME failed\n", ctx->mChanId);
242
243 return ret;
244 }
245
put_packet(Kmpp * ctx,MppPacket packet)246 static MPP_RET put_packet(Kmpp *ctx, MppPacket packet)
247 {
248 (void) packet;
249 MPP_RET ret = MPP_OK;
250
251 if (!ctx->mInitDone)
252 return MPP_ERR_INIT;
253
254 return ret;
255 }
256
get_frame(Kmpp * ctx,MppFrame * frame)257 static MPP_RET get_frame(Kmpp *ctx, MppFrame *frame)
258 {
259 (void)frame;
260 if (!ctx->mInitDone)
261 return MPP_ERR_INIT;
262
263 return MPP_OK;
264 }
265
put_frame(Kmpp * ctx,MppFrame frame)266 static MPP_RET put_frame(Kmpp *ctx, MppFrame frame)
267 {
268 MPP_RET ret = MPP_OK;
269 KmppShmPtr *ptr = NULL;
270 rk_s32 size;
271
272 if (!ctx)
273 return MPP_ERR_VALUE;
274
275 if (!ctx->mInitDone)
276 return MPP_ERR_INIT;
277
278 if (!__check_is_mpp_frame(frame)) {
279 MppFrameImpl *impl = (MppFrameImpl *)frame;
280
281 if (ctx->mKframe == NULL)
282 kmpp_frame_get(&ctx->mKframe);
283
284 kmpp_frame_set_width(ctx->mKframe, impl->width);
285 kmpp_frame_set_height(ctx->mKframe, impl->height);
286 kmpp_frame_set_hor_stride(ctx->mKframe, impl->hor_stride);
287 kmpp_frame_set_ver_stride(ctx->mKframe, impl->ver_stride);
288 kmpp_frame_set_fmt(ctx->mKframe, impl->fmt);
289 kmpp_frame_set_eos(ctx->mKframe, impl->eos);
290 kmpp_frame_set_pts(ctx->mKframe, impl->pts);
291 kmpp_frame_set_dts(ctx->mKframe, impl->dts);
292 kmpp_frame_set_offset_x(ctx->mKframe, impl->offset_x);
293 kmpp_frame_set_offset_y(ctx->mKframe, impl->offset_y);
294 kmpp_frame_set_hor_stride_pixel(ctx->mKframe, impl->hor_stride_pixel);
295
296 if (impl->buffer) {
297 kmpp_frame_set_buf_fd(ctx->mKframe, mpp_buffer_get_fd(impl->buffer));
298 } else {
299 mpp_loge_f("kmpp put_frame buf is NULL\n");
300 return MPP_NOK;
301 }
302
303 if (mpp_frame_has_meta(frame)) {
304 MppMeta meta = mpp_frame_get_meta(frame);
305 MppPacket packet = NULL;
306
307 mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet);
308 ctx->mPacket = packet;
309
310 /* set roi */
311 {
312 MppEncROICfg *roi_data = NULL;
313 MppEncROICfgLegacy roi_data0;
314
315 mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void**)&roi_data);
316 if (roi_data) {
317 roi_data0.change = 1;
318 roi_data0.number = roi_data->number;
319 memcpy(roi_data0.regions, roi_data->regions, roi_data->number * sizeof(MppEncROIRegion));
320 ctx->mApi->control(ctx, MPP_ENC_SET_ROI_CFG, &roi_data0);
321 }
322 }
323
324 /* set osd */
325 {
326 MppEncOSDData3 *osd_data3 = NULL;
327
328 mpp_meta_get_ptr(meta, KEY_OSD_DATA3, (void**)&osd_data3);
329 if (osd_data3) {
330 osd_data3->change = 1;
331 ctx->mApi->control(ctx, MPP_ENC_SET_OSD_DATA_CFG, osd_data3);
332 }
333 }
334 }
335
336 ptr = kmpp_obj_to_shm(ctx->mKframe);
337 size = kmpp_obj_to_shm_size(ctx->mKframe);
338 } else {
339 ptr = kmpp_obj_to_shm(frame);
340 size = kmpp_obj_to_shm_size(frame);
341 }
342
343 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_IN_FRM_RDY, 0, size, ptr);
344 if (ret)
345 mpp_err("chan %d VCODEC_CHAN_IN_FRM_RDY failed\n", ctx->mChanId);
346
347 return ret;
348 }
349
get_packet(Kmpp * ctx,MppPacket * packet)350 static MPP_RET get_packet(Kmpp *ctx, MppPacket *packet)
351 {
352 RK_S32 ret;
353
354 if (!ctx)
355 return MPP_ERR_VALUE;
356
357 if (!ctx->mInitDone)
358 return MPP_ERR_INIT;
359
360 struct timeval timeout;
361 fd_set read_fds;
362
363 FD_ZERO(&read_fds);
364 FD_SET(ctx->mClientFd, &read_fds);
365
366 memcpy(&timeout, &ctx->mTimeout, sizeof(timeout));
367 ret = select(ctx->mClientFd + 1, &read_fds, NULL, NULL, &timeout);
368 if (ret <= 0)
369 return MPP_NOK;
370
371 if (FD_ISSET(ctx->mClientFd, &read_fds)) {
372 KmppShmPtr sptr;
373 MppPacket pkt = NULL;
374 KmppPacket kmpp_pkt = NULL;
375 RK_S32 len;
376 RK_U32 flag;
377 KmppShmPtr pos;
378 RK_S64 dts;
379 RK_S64 pts;
380
381 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_OUT_PKT_RDY,
382 0, sizeof(KmppShmPtr), &sptr);
383 if (ret) {
384 mpp_err("chan %d VCODEC_CHAN_OUT_PKT_RDY failed\n", ctx->mChanId);
385 return MPP_NOK;
386 }
387
388 kmpp_obj_get_by_sptr_f(&kmpp_pkt, &sptr);
389 kmpp_packet_get_flag(kmpp_pkt, &flag);
390 kmpp_packet_get_length(kmpp_pkt, &len);
391 kmpp_packet_get_pos(kmpp_pkt, &pos);
392 kmpp_packet_get_dts(kmpp_pkt, &dts);
393 kmpp_packet_get_pts(kmpp_pkt, &pts);
394
395 if (ctx->mPacket) {
396 void *dst;
397
398 pkt = ctx->mPacket;
399 ctx->mPacket = NULL;
400 if (pos.uptr) {
401 dst = mpp_packet_get_pos(pkt);
402 memcpy(dst, pos.uptr, len);
403 }
404
405 kmpp_packet_put(kmpp_pkt);
406 mpp_packet_set_length(pkt, len);
407 } else {
408 mpp_packet_init(&pkt, pos.uptr, len);
409 mpp_packet_set_release(pkt, kmpp_release_venc_packet, ctx, kmpp_pkt);
410 }
411
412 mpp_packet_set_dts(pkt, dts);
413 mpp_packet_set_pts(pkt, pts);
414 mpp_packet_set_flag(pkt, flag);
415 if (flag & MPP_PACKET_FLAG_INTRA) {
416 MppMeta meta = mpp_packet_get_meta(pkt);
417
418 mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, 1);
419 }
420 *packet = pkt;
421 }
422
423 return MPP_OK;
424 }
425
release_packet(Kmpp * ctx,MppPacket * packet)426 static MPP_RET release_packet(Kmpp *ctx, MppPacket *packet)
427 {
428 KmppPacket pkt = (KmppPacket) * packet;
429
430 if (!ctx)
431 return MPP_ERR_VALUE;
432
433 if (!ctx->mInitDone)
434 return MPP_ERR_INIT;
435
436 if (*packet == NULL)
437 return MPP_NOK;
438
439 if (ctx->mClientFd < 0)
440 return MPP_NOK;
441
442 kmpp_packet_put(pkt);
443
444 return MPP_OK;
445 }
446
poll(Kmpp * ctx,MppPortType type,MppPollType timeout)447 static MPP_RET poll(Kmpp *ctx, MppPortType type, MppPollType timeout)
448 {
449 MPP_RET ret = MPP_NOK;
450 (void)type;
451 (void)timeout;
452
453 if (!ctx->mInitDone)
454 return MPP_ERR_INIT;
455
456 return ret;
457 }
458
dequeue(Kmpp * ctx,MppPortType type,MppTask * task)459 static MPP_RET dequeue(Kmpp *ctx, MppPortType type, MppTask *task)
460 {
461 MPP_RET ret = MPP_NOK;
462 (void)type;
463 (void)task;
464
465 if (!ctx->mInitDone)
466 return MPP_ERR_INIT;
467
468 return ret;
469 }
470
enqueue(Kmpp * ctx,MppPortType type,MppTask task)471 static MPP_RET enqueue(Kmpp *ctx, MppPortType type, MppTask task)
472 {
473 MPP_RET ret = MPP_NOK;
474 (void)type;
475 (void)task;
476
477 if (!ctx->mInitDone)
478 return MPP_ERR_INIT;
479
480 return ret;
481 }
482
control(Kmpp * ctx,MpiCmd cmd,MppParam param)483 static MPP_RET control(Kmpp *ctx, MpiCmd cmd, MppParam param)
484 {
485 MPP_RET ret = MPP_NOK;
486 RK_U32 size = 0;
487 void *arg = param;
488
489 if (!ctx)
490 return MPP_ERR_VALUE;
491
492 switch (cmd) {
493 case MPP_ENC_SET_CFG :
494 case MPP_ENC_GET_CFG : {
495 KmppObj obj = (KmppObj)param;
496
497 if (kmpp_obj_is_kobj(obj)) {
498 arg = kmpp_obj_to_shm(obj);
499 size = kmpp_obj_to_shm_size(obj);
500 } else {
501 mpp_loge("can not set non-kobj %p to kmpp\n", obj);
502 return MPP_NOK;
503 }
504 } break;
505 case MPP_ENC_SET_HEADER_MODE :
506 case MPP_ENC_SET_SEI_CFG : {
507 size = sizeof(RK_U32);
508 } break;
509 case MPP_ENC_GET_REF_CFG :
510 case MPP_ENC_SET_REF_CFG : {
511 size = sizeof(MppEncRefParam);
512 } break;
513 case MPP_ENC_GET_ROI_CFG:
514 case MPP_ENC_SET_ROI_CFG: {
515 size = sizeof(MppEncROICfgLegacy);
516 } break;
517 case MPP_ENC_SET_JPEG_ROI_CFG :
518 case MPP_ENC_GET_JPEG_ROI_CFG : {
519 size = sizeof(MppJpegROICfg);
520 } break;
521 case MPP_ENC_SET_OSD_DATA_CFG: {
522 size = sizeof(MppEncOSDData3);
523 } break;
524 case MPP_ENC_SET_USERDATA: {
525 size = sizeof(MppEncUserData);
526 } break;
527 case MPP_SET_VENC_INIT_KCFG: {
528 KmppObj obj = param;
529
530 arg = kmpp_obj_to_shm(obj);
531 size = kmpp_obj_to_shm_size(obj);
532 } break;
533 case MPP_SET_SELECT_TIMEOUT: {
534 struct timeval *p = (struct timeval *)param;
535 ctx->mTimeout.tv_sec = p->tv_sec;
536 ctx->mTimeout.tv_usec = p->tv_usec;
537 return MPP_OK;
538 } break;
539 case MPP_ENC_SET_IDR_FRAME: {
540 size = 0;
541 } break;
542 default : {
543 size = 0;
544 return MPP_OK;
545 } break;
546 }
547 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_CONTROL, cmd, size, arg);
548 if (ret)
549 mpp_err("chan %d VCODEC_CHAN_CONTROL failed\n", ctx->mChanId);
550
551 return ret;
552 }
553
reset(Kmpp * ctx)554 static MPP_RET reset(Kmpp *ctx)
555 {
556 MPP_RET ret = MPP_OK;
557
558 if (!ctx)
559 return MPP_ERR_VALUE;
560 if (ctx->mChanDup)
561 return MPP_OK;
562 if (!ctx->mInitDone)
563 return MPP_ERR_INIT;
564
565 ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_RESET, 0, 0, 0);
566 if (ret)
567 mpp_err("chan %d VCODEC_CHAN_RESET failed\n", ctx->mChanId);
568
569 return ret;
570 }
571
notify_flag(Kmpp * ctx,RK_U32 flag)572 static MPP_RET notify_flag(Kmpp *ctx, RK_U32 flag)
573 {
574 (void)flag;
575 (void)ctx;
576
577 return MPP_NOK;
578 }
579
notify(Kmpp * ctx,MppBufferGroup group)580 static MPP_RET notify(Kmpp *ctx, MppBufferGroup group)
581 {
582 MPP_RET ret = MPP_OK;
583 (void)group;
584
585 switch (ctx->mType) {
586 case MPP_CTX_DEC : {
587 } break;
588 default : {
589 } break;
590 }
591
592 return ret;
593 }
594
get_fd(Kmpp * ctx,RK_S32 * fd)595 static MPP_RET get_fd(Kmpp *ctx, RK_S32 *fd)
596 {
597 MPP_RET ret = MPP_OK;
598
599 if (!ctx)
600 return MPP_ERR_VALUE;
601
602 if (ctx->mClientFd >= 0)
603 *fd = fcntl(ctx->mClientFd, F_DUPFD_CLOEXEC, 3);
604 else
605 *fd = -1;
606
607 if (*fd < 0)
608 ret = MPP_NOK;
609
610 return ret;
611 }
612
close_fd(Kmpp * ctx,RK_S32 fd)613 static MPP_RET close_fd(Kmpp *ctx, RK_S32 fd)
614 {
615 if (fd >= 0)
616 close(fd);
617 (void)ctx;
618 return MPP_OK;
619 }
620
621 static KmppOps ops = {
622 .open_client = open_client,
623 .init = init,
624 .start = start,
625 .stop = stop,
626 .pause = mpp_pause,
627 .resume = resume,
628 .put_packet = put_packet,
629 .get_frame = get_frame,
630 .put_frame = put_frame,
631 .get_packet = get_packet,
632 .release_packet = release_packet,
633 .poll = poll,
634 .dequeue = dequeue,
635 .enqueue = enqueue,
636 .reset = reset,
637 .control = control,
638 .notify_flag = notify_flag,
639 .notify = notify,
640 .get_fd = get_fd,
641 .close_fd = close_fd,
642 .clear = clear,
643 };
644
mpp_get_api(Kmpp * ctx)645 void mpp_get_api(Kmpp *ctx)
646 {
647 if (!ctx)
648 return;
649
650 ctx->mApi = &ops;
651 }
652