xref: /rockchip-linux_mpp/kmpp/kmpp.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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