xref: /rockchip-linux_mpp/mpp/base/mpp_buf_slot.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define  MODULE_TAG "mpp_buf_slot"
7 
8 #include <string.h>
9 
10 #include "mpp_mem.h"
11 #include "mpp_env.h"
12 #include "mpp_list.h"
13 #include "mpp_debug.h"
14 #include "mpp_common.h"
15 
16 #include "mpp_frame_impl.h"
17 #include "mpp_buf_slot.h"
18 #include "mpp_compat_impl.h"
19 #include "rk_mpp_cfg.h"
20 
21 #define BUF_SLOT_DBG_FUNCTION           (0x00000001)
22 #define BUF_SLOT_DBG_SETUP              (0x00000002)
23 #define BUF_SLOT_DBG_INFO_CHANGE        (0x00000004)
24 #define BUF_SLOT_DBG_OPS_RUNTIME        (0x00000010)
25 #define BUF_SLOT_DBG_BUFFER             (0x00000100)
26 #define BUF_SLOT_DBG_FRAME              (0x00000200)
27 #define BUF_SLOT_DBG_BUF_UESD           (0x00000400)
28 #define BUF_SLOT_DBG_INFO_SET           (0x00000800)
29 #define BUF_SLOT_DBG_OPS_HISTORY        (0x10000000)
30 #define BUF_SLOT_DBG_ALL                (0x10000011)
31 
32 #define buf_slot_dbg(flag, fmt, ...)    _mpp_dbg(buf_slot_debug, flag, fmt, ## __VA_ARGS__)
33 
34 static RK_U32 buf_slot_debug = 0;
35 static RK_U32 buf_slot_idx = 0;
36 static RK_U32 use_legacy_align = 0;
37 
38 #define slot_assert(impl, cond) do {                                    \
39     if (!(cond)) {                                                      \
40         dump_slots(impl);                                               \
41         mpp_err("Assertion %s failed at %s:%d\n",                       \
42                MPP_STRINGS(cond), __FUNCTION__, __LINE__);              \
43         abort();                                                        \
44     }                                                                   \
45 } while (0)
46 
47 typedef struct MppBufSlotEntry_t MppBufSlotEntry;
48 typedef struct MppBufSlotsImpl_t MppBufSlotsImpl;
49 
50 #define SLOT_OPS_MAX_COUNT              1024
51 
52 typedef enum MppBufSlotOps_e {
53     // status opertaion
54     SLOT_INIT,
55     SLOT_SET_ON_USE,
56     SLOT_CLR_ON_USE,
57     SLOT_SET_NOT_READY,
58     SLOT_CLR_NOT_READY,
59     SLOT_SET_CODEC_READY,
60     SLOT_CLR_CODEC_READY,
61     SLOT_SET_CODEC_USE,
62     SLOT_CLR_CODEC_USE,
63     SLOT_SET_HAL_INPUT,
64     SLOT_CLR_HAL_INPUT,
65     SLOT_SET_HAL_OUTPUT,
66     SLOT_CLR_HAL_OUTPUT,
67     SLOT_SET_QUEUE_USE,
68     SLOT_CLR_QUEUE_USE,
69 
70     // queue operation
71     SLOT_ENQUEUE,
72     SLOT_ENQUEUE_OUTPUT = SLOT_ENQUEUE,
73     SLOT_ENQUEUE_DISPLAY,
74     SLOT_ENQUEUE_DEINTER,
75     SLOT_ENQUEUE_CONVERT,
76     SLOT_DEQUEUE,
77     SLOT_DEQUEUE_OUTPUT = SLOT_DEQUEUE,
78     SLOT_DEQUEUE_DISPLAY,
79     SLOT_DEQUEUE_DEINTER,
80     SLOT_DEQUEUE_CONVERT,
81 
82     // value operation
83     SLOT_SET_EOS,
84     SLOT_CLR_EOS,
85     SLOT_SET_FRAME,
86     SLOT_CLR_FRAME,
87     SLOT_SET_BUFFER,
88     SLOT_CLR_BUFFER,
89 } MppBufSlotOps;
90 
91 static const char op_string[][16] = {
92     "init           ",
93     "set on use     ",
94     "clr on use     ",
95     "set not ready  ",
96     "set ready      ",
97     "set codec ready",
98     "clr codec ready",
99     "set codec use  ",
100     "clr codec use  ",
101     "set hal input  ",
102     "clr hal input  ",
103     "set hal output ",
104     "clr hal output ",
105     "set queue use  ",
106     "clr queue use  ",
107 
108     "enqueue output ",
109     "enqueue display",
110     "enqueue deint  ",
111     "enqueue convert",
112     "dequeue output ",
113     "dequeue display",
114     "dequeue deint  ",
115     "dequeue convert",
116 
117     "set eos        ",
118     "clr eos        ",
119     "set frame      ",
120     "clr frame      ",
121     "set buffer     ",
122     "clr buffer     ",
123 };
124 
125 static const MppBufSlotOps set_flag_op[SLOT_USAGE_BUTT] = {
126     SLOT_SET_CODEC_READY,
127     SLOT_SET_CODEC_USE,
128     SLOT_SET_HAL_INPUT,
129     SLOT_SET_HAL_OUTPUT,
130     SLOT_SET_QUEUE_USE,
131 };
132 
133 static const MppBufSlotOps clr_flag_op[SLOT_USAGE_BUTT] = {
134     SLOT_CLR_CODEC_READY,
135     SLOT_CLR_CODEC_USE,
136     SLOT_CLR_HAL_INPUT,
137     SLOT_CLR_HAL_OUTPUT,
138     SLOT_CLR_QUEUE_USE,
139 };
140 
141 static const MppBufSlotOps set_val_op[SLOT_PROP_BUTT] = {
142     SLOT_SET_EOS,
143     SLOT_SET_FRAME,
144     SLOT_SET_BUFFER,
145 };
146 
147 typedef union SlotStatus_u {
148     RK_U32 val;
149     struct {
150         // status flags
151         RK_U32  on_used     : 1;
152         RK_U32  not_ready   : 1;        // buffer slot is filled or not
153         RK_U32  codec_use   : 1;        // buffer slot is used by codec ( dpb reference )
154         RK_U32  hal_output  : 2;        // buffer slot is set to hw output will ready when hw done
155         RK_U32  hal_use     : 8;        // buffer slot is used by hardware
156         RK_U32  queue_use   : 5;        // buffer slot is used in different queue
157 
158         // value flags
159         RK_U32  eos         : 1;        // buffer slot is last buffer slot from codec
160         RK_U32  has_buffer  : 1;
161         RK_U32  has_frame   : 1;
162     };
163 } SlotStatus;
164 
165 typedef struct MppBufSlotLog_t {
166     RK_S32              index;
167     MppBufSlotOps       ops;
168     SlotStatus          status_in;
169     SlotStatus          status_out;
170 } MppBufSlotLog;
171 
172 typedef struct MppBufSlotLogs_t {
173     pthread_mutex_t     lock;
174     RK_U16              max_count;
175     RK_U16              log_count;
176     RK_U16              log_write;
177     RK_U16              log_read;
178     MppBufSlotLog       *logs;
179 } MppBufSlotLogs;
180 
181 struct MppBufSlotEntry_t {
182     MppBufSlotsImpl     *slots;
183     struct list_head    list;
184     SlotStatus          status;
185     RK_S32              index;
186 
187     RK_U32              eos;
188     MppFrame            frame;
189     MppBuffer           buffer;
190 };
191 
192 struct MppBufSlotsImpl_t {
193     MppMutex            lock;
194     RK_U32              slots_idx;
195 
196     // status tracing
197     RK_U32              decode_count;
198     RK_U32              display_count;
199 
200     MppCodingType       coding_type;
201 
202     // if slot changed, all will be hold until all slot is unused
203     RK_U32              info_changed;
204     RK_S32              info_change_slot_idx;
205     RK_S32              new_count;
206 
207     // slot infomation for info change and eos
208     RK_U32              eos;
209 
210     // buffer parameter, default alignement is 16
211     MppSysCfg           sys_cfg;
212     AlignFunc           hal_hor_align;          // default NULL
213     AlignFunc           hal_ver_align;          // default NULL
214     AlignFunc           hal_len_align;          // default NULL
215     AlignFunc           hal_width_align;        // default NULL
216     SlotHalFbcAdjCfg    hal_fbc_adj_cfg;        // hal fbc frame adjust config
217     size_t              buf_size;
218     RK_S32              buf_count;
219     RK_S32              used_count;
220     RK_U32              align_chk_log_env;
221     RK_U32              align_chk_log_en;
222     // buffer size equal to (h_stride * v_stride) * numerator / denominator
223     // internal parameter
224     RK_U32              numerator;
225     RK_U32              denominator;
226 
227     // callback for free slot notify
228     MppCbCtx            callback;
229 
230     // NOTE: use MppFrame to store the buffer/display infomation
231     //       any buffer related infomation change comparing to previous frame will
232     //       trigger a buffer info changed requirement
233     //       any display related infomation change comparing to pevious frame will
234     //       trigger a display info changed requirement
235     MppFrame            info;
236     MppFrame            info_set;
237 
238     // list for display
239     struct list_head    queue[QUEUE_BUTT];
240 
241     // list for log
242     MppBufSlotLogs      *logs;
243 
244     MppBufSlotEntry     *slots;
245 };
246 
247 typedef struct MppBufSlotInfoSet_t {
248     RK_U32 h_stride_by_pixel;
249     RK_U32 h_stride_by_byte;
250     RK_U32 v_stride;
251     RK_U32 size_total;
252 } MppBufSlotInfoSet;
253 
default_align_16(RK_U32 val)254 static RK_U32 default_align_16(RK_U32 val)
255 {
256     return MPP_ALIGN(val, 16);
257 }
258 
259 /* Based on drm_gem_framebuffer_helper.c drm_gem_afbc_min_size() */
get_afbc_min_size(RK_S32 width,RK_S32 height,RK_S32 bpp)260 static RK_S32 get_afbc_min_size(RK_S32 width, RK_S32 height, RK_S32 bpp)
261 {
262 #define AFBC_HEADER_SIZE 16
263 #define AFBC_HDR_ALIGN 64
264 #define AFBC_SUPERBLOCK_PIXELS 256
265 #define AFBC_SUPERBLOCK_ALIGNMENT 128
266 
267     RK_S32 n_blocks, hdr_alignment, size;
268 
269     /* AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 and !AFBC_FORMAT_MOD_TILED */
270     width = MPP_ALIGN(width, 16);
271     height = MPP_ALIGN(height, 16);
272     hdr_alignment = AFBC_HDR_ALIGN;
273 
274     n_blocks = (width * height) / AFBC_SUPERBLOCK_PIXELS;
275 
276     size = MPP_ALIGN(n_blocks * AFBC_HEADER_SIZE, hdr_alignment);
277     size += n_blocks * MPP_ALIGN(bpp * AFBC_SUPERBLOCK_PIXELS / 8,
278                                  AFBC_SUPERBLOCK_ALIGNMENT);
279     return size;
280 }
281 
prepare_info_set_legacy(MppBufSlotsImpl * impl,MppFrame frame,MppBufSlotInfoSet * info_set,RK_U32 force_def_align)282 static void prepare_info_set_legacy(MppBufSlotsImpl *impl, MppFrame frame,
283                                     MppBufSlotInfoSet *info_set,
284                                     RK_U32 force_def_align)
285 {
286     const RK_U32 width  = mpp_frame_get_width(frame);
287     const RK_U32 height = mpp_frame_get_height(frame);
288     const MppFrameFormat fmt = mpp_frame_get_fmt(frame);
289     RK_U32 depth = ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP_10BIT ||
290                     (fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV422SP_10BIT ||
291                     (fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP_10BIT) ? 10 : 8;
292     RK_U32 codec_hor_stride = mpp_frame_get_hor_stride(frame);
293     RK_U32 codec_ver_stride = mpp_frame_get_ver_stride(frame);
294     RK_U32 coded_width = (impl->hal_width_align) ?
295                          (impl->hal_width_align(width)) : width;
296 
297     RK_U32 hal_hor_stride = (codec_hor_stride) ?
298                             (impl->hal_hor_align(codec_hor_stride)) :
299                             (impl->hal_hor_align(coded_width * depth >> 3));
300     RK_U32 hal_ver_stride = (codec_ver_stride) ?
301                             (impl->hal_ver_align(codec_ver_stride)) :
302                             (impl->hal_ver_align(height));
303     RK_U32 hor_stride_pixel;
304     RK_S32 size;
305 
306     hal_hor_stride = (force_def_align && codec_hor_stride) ? codec_hor_stride : hal_hor_stride;
307     hal_ver_stride = (force_def_align && codec_ver_stride) ? codec_ver_stride : hal_ver_stride;
308 
309     if (MPP_FRAME_FMT_IS_FBC(fmt)) {
310         /*fbc stride default 64 align*/
311         if (*compat_ext_fbc_hdr_256_odd)
312             hal_hor_stride = (MPP_ALIGN(width, 256) | 256) * depth >> 3;
313         else
314             hal_hor_stride = MPP_ALIGN(width, 64) * depth >> 3;
315     }
316 
317     switch (fmt & MPP_FRAME_FMT_MASK) {
318     case MPP_FMT_YUV420SP_10BIT:
319     case MPP_FMT_YUV422SP_10BIT:
320     case MPP_FMT_YUV444SP_10BIT: {
321         hor_stride_pixel = hal_hor_stride * 8 / 10;
322     } break;
323     case MPP_FMT_YUV422_YVYU:
324     case MPP_FMT_YUV422_YUYV:
325     case MPP_FMT_RGB565:
326     case MPP_FMT_BGR565: {
327         hor_stride_pixel = hal_hor_stride / 2;
328     } break;
329     case MPP_FMT_RGB888:
330     case MPP_FMT_BGR888: {
331         hor_stride_pixel = hal_hor_stride / 3;
332     } break;
333     default : {
334         hor_stride_pixel = hal_hor_stride;
335     } break;
336     }
337 
338     size = hal_hor_stride * hal_ver_stride;
339 
340     if (MPP_FRAME_FMT_IS_FBC(fmt)) {
341         hor_stride_pixel = MPP_ALIGN(hor_stride_pixel, 64);
342         switch ((fmt & MPP_FRAME_FMT_MASK)) {
343         case MPP_FMT_YUV420SP_10BIT : {
344             size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 15);
345         } break;
346         case MPP_FMT_YUV422SP_10BIT : {
347             size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 20);
348         } break;
349         case MPP_FMT_YUV420SP : {
350             size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 12);
351         } break;
352         case MPP_FMT_YUV422SP : {
353             size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 16);
354         } break;
355         case MPP_FMT_YUV444SP : {
356             size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 24);
357         } break;
358         case MPP_FMT_YUV444SP_10BIT : {
359             size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 30);
360         } break;
361         default : {
362             size = hal_hor_stride * hal_ver_stride * 3 / 2;
363             mpp_err("dec out fmt is no support");
364         } break;
365         }
366         mpp_frame_set_fbc_size(frame, size);
367     } else {
368         size *= impl->numerator;
369         size /= impl->denominator;
370         size = impl->hal_len_align ? (RK_S32)impl->hal_len_align(hal_hor_stride * hal_ver_stride) : size;
371     }
372 
373     info_set->h_stride_by_byte = hal_hor_stride;
374     info_set->v_stride = hal_ver_stride;
375     info_set->h_stride_by_pixel = hor_stride_pixel;
376     info_set->size_total = size;
377 }
378 
prepare_info_set_by_sys_cfg(MppBufSlotsImpl * impl,MppFrame frame,MppBufSlotInfoSet * info_set)379 static void prepare_info_set_by_sys_cfg(MppBufSlotsImpl *impl, MppFrame frame,
380                                         MppBufSlotInfoSet *info_set)
381 {
382     const RK_U32 width  = mpp_frame_get_width(frame);
383     const RK_U32 height = mpp_frame_get_height(frame);
384     const RK_U32 codec_hor_stride = mpp_frame_get_hor_stride(frame);
385     const RK_U32 codec_ver_stride = mpp_frame_get_ver_stride(frame);
386     const MppFrameFormat fmt = mpp_frame_get_fmt(frame);
387 
388     /* set correct parameter */
389     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:enable", 1);
390     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:type", impl->coding_type);
391     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_codec", fmt & MPP_FRAME_FMT_MASK);
392     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_fbc", fmt & MPP_FRAME_FBC_MASK);
393     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_hdr", fmt & MPP_FRAME_HDR_MASK);
394     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:width", width);
395     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:height", height);
396     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_byte", codec_hor_stride);
397     mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:v_stride", codec_ver_stride);
398 
399     /* get result */
400     mpp_sys_cfg_ioctl(impl->sys_cfg);
401 
402     mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_byte", &info_set->h_stride_by_byte);
403     mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_pixel", &info_set->h_stride_by_pixel);
404     mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:v_stride", &info_set->v_stride);
405     mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:size_total", &info_set->size_total);
406 
407     return;
408 }
409 
generate_info_set(MppBufSlotsImpl * impl,MppFrame frame,RK_U32 force_def_align)410 static void generate_info_set(MppBufSlotsImpl *impl, MppFrame frame, RK_U32 force_def_align)
411 {
412     const RK_U32 width  = mpp_frame_get_width(frame);
413     const RK_U32 height = mpp_frame_get_height(frame);
414     const MppFrameFormat fmt = mpp_frame_get_fmt(frame);
415     MppBufSlotInfoSet legacy_info_set;
416     MppBufSlotInfoSet sys_cfg_info_set;
417     MppBufSlotInfoSet *info_set_ptr = NULL;
418     MppFrameImpl *info_set_impl = NULL;
419     MppFrameImpl *frame_impl = NULL;
420 
421     prepare_info_set_legacy(impl, frame, &legacy_info_set, force_def_align);
422     prepare_info_set_by_sys_cfg(impl, frame, &sys_cfg_info_set);
423 
424     mpp_frame_set_width(impl->info_set, width);
425     mpp_frame_set_height(impl->info_set, height);
426     mpp_frame_set_fmt(impl->info_set, fmt);
427     info_set_ptr = use_legacy_align ? &legacy_info_set : &sys_cfg_info_set;
428     mpp_frame_set_hor_stride(impl->info_set, info_set_ptr->h_stride_by_byte);
429     mpp_frame_set_ver_stride(impl->info_set, info_set_ptr->v_stride);
430     mpp_frame_set_hor_stride_pixel(impl->info_set, info_set_ptr->h_stride_by_pixel);
431     mpp_frame_set_buf_size(impl->info_set, info_set_ptr->size_total);
432     mpp_frame_set_buf_size(frame, info_set_ptr->size_total);
433     mpp_frame_set_hor_stride(frame, info_set_ptr->h_stride_by_byte);
434     mpp_frame_set_ver_stride(frame, info_set_ptr->v_stride);
435     mpp_frame_set_hor_stride_pixel(frame, info_set_ptr->h_stride_by_pixel);
436     impl->buf_size = info_set_ptr->size_total;
437 
438     if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) {
439         /*
440          * The decode hw only support 1/2 scaling in width and height,
441          * downscale output image only support raster mode with 8bit depth.
442          */
443         RK_U32 down_scale_ver = MPP_ALIGN(mpp_frame_get_height(frame) >> 1, 16);
444         RK_U32 down_scale_hor = MPP_ALIGN(mpp_frame_get_width(frame) >> 1, 16);
445         RK_U32 downscale_buf_size;
446         RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor;
447 
448         switch ((fmt & MPP_FRAME_FMT_MASK)) {
449         case MPP_FMT_YUV400 : {
450             downscale_buf_size = down_scale_y_virstride;
451         } break;
452         case MPP_FMT_YUV420SP_10BIT :
453         case MPP_FMT_YUV420SP : {
454             downscale_buf_size = down_scale_y_virstride * 3 / 2;
455         } break;
456         case MPP_FMT_YUV422SP_10BIT :
457         case MPP_FMT_YUV422SP : {
458             downscale_buf_size = down_scale_y_virstride * 2;
459         } break;
460         case MPP_FMT_YUV444SP_10BIT :
461         case MPP_FMT_YUV444SP : {
462             downscale_buf_size = down_scale_y_virstride * 3;
463         } break;
464         default : {
465             downscale_buf_size = down_scale_y_virstride * 3 / 2;
466         } break;
467         }
468         downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16);
469         impl->buf_size += downscale_buf_size;
470         mpp_frame_set_buf_size(impl->info_set, impl->buf_size);
471         mpp_frame_set_buf_size(frame, impl->buf_size);
472     }
473     info_set_impl = (MppFrameImpl *)impl->info_set;
474     frame_impl    = (MppFrameImpl *)frame;
475     info_set_impl->color_range      = frame_impl->color_range;
476     info_set_impl->color_primaries  = frame_impl->color_primaries;
477     info_set_impl->color_trc        = frame_impl->color_trc;
478     info_set_impl->colorspace       = frame_impl->colorspace;
479     info_set_impl->chroma_location  = frame_impl->chroma_location;
480 
481     if (impl->align_chk_log_en) {
482         impl->align_chk_log_en = 0;
483         if (legacy_info_set.h_stride_by_pixel != sys_cfg_info_set.h_stride_by_pixel)
484             mpp_logi("mismatch h_stride_by_pixel %d - %d\n",
485                      legacy_info_set.h_stride_by_pixel,
486                      sys_cfg_info_set.h_stride_by_pixel);
487         if (legacy_info_set.h_stride_by_byte != sys_cfg_info_set.h_stride_by_byte)
488             mpp_logi("mismatch h_stride_by_byte %d - %d\n",
489                      legacy_info_set.h_stride_by_byte,
490                      sys_cfg_info_set.h_stride_by_byte);
491         if (legacy_info_set.v_stride != sys_cfg_info_set.v_stride)
492             mpp_logi("mismatch v_stride %d - %d\n",
493                      legacy_info_set.v_stride,
494                      sys_cfg_info_set.v_stride);
495         if (legacy_info_set.size_total != sys_cfg_info_set.size_total)
496             mpp_logi("mismatch size_total %d - %d\n",
497                      legacy_info_set.size_total,
498                      sys_cfg_info_set.size_total);
499     }
500 }
501 
502 #define dump_slots(...) _dump_slots(__FUNCTION__, ## __VA_ARGS__)
503 
buf_slot_logs_reset(MppBufSlotLogs * logs)504 static void buf_slot_logs_reset(MppBufSlotLogs *logs)
505 {
506     logs->log_count = 0;
507     logs->log_write = 0;
508     logs->log_read = 0;
509 }
510 
buf_slot_logs_init(RK_U32 max_count)511 static MppBufSlotLogs *buf_slot_logs_init(RK_U32 max_count)
512 {
513     MppBufSlotLogs *logs = NULL;
514 
515     if (!max_count)
516         return NULL;
517 
518     logs = mpp_malloc_size(MppBufSlotLogs, sizeof(MppBufSlotLogs) +
519                            max_count * sizeof(MppBufSlotLog));
520     if (!logs) {
521         mpp_err_f("failed to create %d buf slot logs\n", max_count);
522         return NULL;
523     }
524 
525     logs->max_count = max_count;
526     logs->logs = (MppBufSlotLog *)(logs + 1);
527     buf_slot_logs_reset(logs);
528 
529     return logs;
530 }
531 
buf_slot_logs_deinit(MppBufSlotLogs * logs)532 static void buf_slot_logs_deinit(MppBufSlotLogs *logs)
533 {
534     MPP_FREE(logs);
535 }
536 
buf_slot_logs_write(MppBufSlotLogs * logs,RK_S32 index,MppBufSlotOps op,SlotStatus before,SlotStatus after)537 static void buf_slot_logs_write(MppBufSlotLogs *logs, RK_S32 index, MppBufSlotOps op,
538                                 SlotStatus before, SlotStatus after)
539 {
540     MppBufSlotLog *log = NULL;
541 
542     log = &logs->logs[logs->log_write];
543     log->index      = index;
544     log->ops        = op;
545     log->status_in  = before;
546     log->status_out = after;
547 
548     logs->log_write++;
549     if (logs->log_write >= logs->max_count)
550         logs->log_write = 0;
551 
552     if (logs->log_count < logs->max_count)
553         logs->log_count++;
554     else {
555         logs->log_read++;
556         if (logs->log_read >= logs->max_count)
557             logs->log_read = 0;
558     }
559 }
560 
buf_slot_logs_dump(MppBufSlotLogs * logs)561 static void buf_slot_logs_dump(MppBufSlotLogs *logs)
562 {
563     while (logs->log_count) {
564         MppBufSlotLog *log = &logs->logs[logs->log_read];
565 
566         mpp_log("index %2d op: %s status in %08x out %08x",
567                 log->index, op_string[log->ops], log->status_in.val, log->status_out.val);
568 
569         logs->log_read++;
570         if (logs->log_read >= logs->max_count)
571             logs->log_read = 0;
572         logs->log_count--;
573     }
574     mpp_assert(logs->log_read == logs->log_write);
575 }
576 
_dump_slots(const char * caller,MppBufSlotsImpl * impl)577 static void _dump_slots(const char *caller, MppBufSlotsImpl *impl)
578 {
579     MppBufSlotEntry *slot = impl->slots;
580     RK_S32 i;
581 
582     mpp_log("\ncaller %s is dumping slots\n", caller, impl->slots_idx);
583     mpp_log("slots %d %p buffer count %d buffer size %d\n", impl->slots_idx,
584             impl, impl->buf_count, impl->buf_size);
585     mpp_log("decode  count %d\n", impl->decode_count);
586     mpp_log("display count %d\n", impl->display_count);
587 
588     for (i = 0; i < impl->buf_count; i++, slot++) {
589         SlotStatus status = slot->status;
590         mpp_log("slot %2d used %d refer %d decoding %d display %d status %08x\n",
591                 i, status.on_used, status.codec_use, status.hal_use, status.queue_use, status.val);
592     }
593 
594     mpp_log("\nslot operation history:\n\n");
595 
596     if (impl->logs)
597         buf_slot_logs_dump(impl->logs);
598 
599     mpp_assert(0);
600 
601     return;
602 }
603 
slot_ops_with_log(MppBufSlotsImpl * impl,MppBufSlotEntry * slot,MppBufSlotOps op,void * arg)604 static void slot_ops_with_log(MppBufSlotsImpl *impl, MppBufSlotEntry *slot, MppBufSlotOps op, void *arg)
605 {
606     RK_U32 error = 0;
607     RK_S32 index = slot->index;
608     SlotStatus status = slot->status;
609     SlotStatus before = status;
610     switch (op) {
611     case SLOT_INIT : {
612         status.val = 0;
613     } break;
614     case SLOT_SET_ON_USE : {
615         status.on_used = 1;
616     } break;
617     case SLOT_CLR_ON_USE : {
618         status.on_used = 0;
619     } break;
620     case SLOT_SET_NOT_READY : {
621         status.not_ready = 1;
622     } break;
623     case SLOT_CLR_NOT_READY : {
624         status.not_ready = 0;
625     } break;
626     case SLOT_SET_CODEC_READY : {
627         status.not_ready = 0;
628     } break;
629     case SLOT_CLR_CODEC_READY : {
630         status.not_ready = 1;
631     } break;
632     case SLOT_SET_CODEC_USE : {
633         status.codec_use = 1;
634     } break;
635     case SLOT_CLR_CODEC_USE : {
636         status.codec_use = 0;
637     } break;
638     case SLOT_SET_HAL_INPUT : {
639         status.hal_use++;
640     } break;
641     case SLOT_CLR_HAL_INPUT : {
642         if (status.hal_use)
643             status.hal_use--;
644         else {
645             mpp_err("can not clr hal_input on slot %d\n", slot->index);
646             error = 1;
647         }
648     } break;
649     case SLOT_SET_HAL_OUTPUT : {
650         status.hal_output++;
651         status.not_ready  = 1;
652     } break;
653     case SLOT_CLR_HAL_OUTPUT : {
654         if (status.hal_output)
655             status.hal_output--;
656         else
657             mpp_err("can not clr hal_output on slot %d\n", slot->index);
658 
659         // NOTE: set output index ready here
660         if (!status.hal_output)
661             status.not_ready  = 0;
662     } break;
663     case SLOT_SET_QUEUE_USE :
664     case SLOT_ENQUEUE_OUTPUT :
665     case SLOT_ENQUEUE_DISPLAY :
666     case SLOT_ENQUEUE_DEINTER :
667     case SLOT_ENQUEUE_CONVERT : {
668         status.queue_use++;
669     } break;
670     case SLOT_CLR_QUEUE_USE :
671     case SLOT_DEQUEUE_OUTPUT :
672     case SLOT_DEQUEUE_DISPLAY :
673     case SLOT_DEQUEUE_DEINTER :
674     case SLOT_DEQUEUE_CONVERT : {
675         if (status.queue_use)
676             status.queue_use--;
677         else {
678             mpp_err("can not clr queue_use on slot %d\n", slot->index);
679             error = 1;
680         }
681     } break;
682     case SLOT_SET_EOS : {
683         status.eos = 1;
684     } break;
685     case SLOT_CLR_EOS : {
686         status.eos = 0;
687         slot->eos = 0;
688     } break;
689     case SLOT_SET_FRAME : {
690         status.has_frame = (arg) ? (1) : (0);
691     } break;
692     case SLOT_CLR_FRAME : {
693         status.has_frame = 0;
694     } break;
695     case SLOT_SET_BUFFER : {
696         status.has_buffer = (arg) ? (1) : (0);
697     } break;
698     case SLOT_CLR_BUFFER : {
699         status.has_buffer = 0;
700     } break;
701     default : {
702         mpp_err("found invalid operation code %d\n", op);
703         error = 1;
704     } break;
705     }
706     slot->status = status;
707     buf_slot_dbg(BUF_SLOT_DBG_OPS_RUNTIME, "slot %3d index %2d op: %s arg %010p status in %08x out %08x",
708                  impl->slots_idx, index, op_string[op], arg, before.val, status.val);
709     if (impl->logs)
710         buf_slot_logs_write(impl->logs, index, op, before, status);
711     if (error)
712         dump_slots(impl);
713 }
714 
init_slot_entry(MppBufSlotsImpl * impl,RK_S32 pos,RK_S32 count)715 static void init_slot_entry(MppBufSlotsImpl *impl, RK_S32 pos, RK_S32 count)
716 {
717     MppBufSlotEntry *slot = impl->slots;
718     RK_S32 i;
719 
720     for (i = 0; i < count; i++, slot++) {
721         slot->slots = impl;
722         INIT_LIST_HEAD(&slot->list);
723         slot->index = pos + i;
724         slot->frame = NULL;
725         slot_ops_with_log(impl, slot, SLOT_INIT, NULL);
726     }
727 }
728 
729 /*
730  * only called on unref / displayed / decoded
731  *
732  * NOTE: MppFrame will be destroyed outside mpp
733  *       but MppBuffer must dec_ref here
734  */
check_entry_unused(MppBufSlotsImpl * impl,MppBufSlotEntry * entry)735 static RK_S32 check_entry_unused(MppBufSlotsImpl *impl, MppBufSlotEntry *entry)
736 {
737     SlotStatus status = entry->status;
738 
739     if (status.on_used &&
740         !status.not_ready &&
741         !status.codec_use &&
742         !status.hal_output &&
743         !status.hal_use &&
744         !status.queue_use) {
745         if (entry->frame) {
746             slot_ops_with_log(impl, entry, SLOT_CLR_FRAME, entry->frame);
747             mpp_frame_deinit(&entry->frame);
748         }
749         if (entry->buffer) {
750             mpp_buffer_put(entry->buffer);
751             slot_ops_with_log(impl, entry, SLOT_CLR_BUFFER, entry->buffer);
752             entry->buffer = NULL;
753         }
754 
755         slot_ops_with_log(impl, entry, SLOT_CLR_ON_USE, NULL);
756         impl->used_count--;
757         return 1;
758     }
759 
760     return 0;
761 }
762 
clear_slots_impl(MppBufSlotsImpl * impl)763 static void clear_slots_impl(MppBufSlotsImpl *impl)
764 {
765     MppBufSlotEntry *slot = (MppBufSlotEntry *)impl->slots;
766     RK_S32 i;
767 
768     if (impl->sys_cfg)
769         mpp_sys_cfg_put(impl->sys_cfg);
770 
771     for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(impl->queue); i++) {
772         if (!list_empty(&impl->queue[i]))
773             dump_slots(impl);
774 
775         mpp_assert(list_empty(&impl->queue[i]));
776     }
777 
778     for (i = 0; i < impl->buf_count; i++, slot++) {
779         mpp_assert(!slot->status.on_used);
780         if (slot->status.on_used) {
781             dump_slots(impl);
782             mpp_buf_slot_reset(impl, i);
783         }
784     }
785 
786     impl->used_count = 0;
787 
788     if (impl->info)
789         mpp_frame_deinit(&impl->info);
790 
791     if (impl->info_set)
792         mpp_frame_deinit(&impl->info_set);
793 
794     if (impl->logs) {
795         buf_slot_logs_deinit(impl->logs);
796         impl->logs = NULL;
797     }
798 
799     mpp_mutex_destroy(&impl->lock);
800 
801     mpp_free(impl->slots);
802     mpp_free(impl);
803 }
804 
mpp_buf_slot_init(MppBufSlots * slots)805 MPP_RET mpp_buf_slot_init(MppBufSlots *slots)
806 {
807     MppBufSlotsImpl *impl;
808     RK_U32 i;
809 
810     if (!slots) {
811         mpp_err_f("found NULL input\n");
812         return MPP_ERR_NULL_PTR;
813     }
814 
815     impl = mpp_calloc(MppBufSlotsImpl, 1);
816     if (!impl) {
817         *slots = NULL;
818         return MPP_NOK;
819     }
820 
821     mpp_env_get_u32("buf_slot_debug", &buf_slot_debug,
822                     BUF_SLOT_DBG_OPS_HISTORY | BUF_SLOT_DBG_INFO_SET);
823     mpp_env_get_u32("use_legacy_align", &use_legacy_align, 0);
824 
825     do {
826         if (mpp_sys_cfg_get(&impl->sys_cfg)) {
827             mpp_err_f("mpp_sys_cfg_get failed\n");
828             break;
829         }
830 
831         mpp_mutex_init(&impl->lock);
832 
833         for (i = 0; i < MPP_ARRAY_ELEMS(impl->queue); i++) {
834             INIT_LIST_HEAD(&impl->queue[i]);
835         }
836 
837         if (buf_slot_debug & BUF_SLOT_DBG_OPS_HISTORY) {
838             impl->logs = buf_slot_logs_init(SLOT_OPS_MAX_COUNT);
839             if (!impl->logs)
840                 break;
841         }
842 
843         if (mpp_frame_init(&impl->info))
844             break;
845 
846         if (mpp_frame_init(&impl->info_set))
847             break;
848 
849         // slots information default setup
850         impl->hal_hor_align = default_align_16;
851         impl->hal_ver_align = default_align_16;
852         impl->hal_len_align = NULL;
853         impl->numerator     = 9;
854         impl->denominator   = 5;
855         impl->slots_idx     = buf_slot_idx++;
856         impl->info_change_slot_idx = -1;
857         impl->align_chk_log_env = (buf_slot_debug & BUF_SLOT_DBG_INFO_SET) ? 1 : 0;
858         impl->align_chk_log_en = impl->align_chk_log_env;
859 
860         *slots = impl;
861         return MPP_OK;
862     } while (0);
863 
864     clear_slots_impl(impl);
865 
866     *slots = NULL;
867     return MPP_NOK;
868 }
869 
mpp_buf_slot_deinit(MppBufSlots slots)870 MPP_RET mpp_buf_slot_deinit(MppBufSlots slots)
871 {
872     if (!slots) {
873         mpp_err_f("found NULL input\n");
874         return MPP_ERR_NULL_PTR;
875     }
876 
877     clear_slots_impl((MppBufSlotsImpl *)slots);
878     return MPP_OK;
879 }
880 
mpp_buf_slot_setup(MppBufSlots slots,RK_S32 count)881 MPP_RET mpp_buf_slot_setup(MppBufSlots slots, RK_S32 count)
882 {
883     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
884 
885     if (!impl) {
886         mpp_err_f("found NULL input\n");
887         return MPP_ERR_NULL_PTR;
888     }
889 
890     buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p setup: count %d\n", impl, count);
891 
892     mpp_mutex_lock(&impl->lock);
893 
894     if (!impl->slots) {
895         // first slot setup
896         impl->buf_count = impl->new_count = count;
897         impl->slots = mpp_calloc(MppBufSlotEntry, count);
898         init_slot_entry(impl, 0, count);
899         impl->used_count = 0;
900     } else {
901         // record the slot count for info changed ready config
902         if (count > impl->buf_count) {
903             impl->slots = mpp_realloc(impl->slots, MppBufSlotEntry, count);
904             mpp_assert(impl->slots);
905             init_slot_entry(impl, impl->buf_count, (count - impl->buf_count));
906         }
907         impl->new_count = count;
908     }
909 
910     mpp_mutex_unlock(&impl->lock);
911 
912     return MPP_OK;
913 }
914 
mpp_buf_slot_is_changed(MppBufSlots slots)915 RK_U32 mpp_buf_slot_is_changed(MppBufSlots slots)
916 {
917     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
918     RK_U32 info_changed = 0;
919 
920     if (!impl) {
921         mpp_err_f("found NULL input\n");
922         return 0;
923     }
924 
925     mpp_mutex_lock(&impl->lock);
926     info_changed = impl->info_changed;
927     mpp_mutex_unlock(&impl->lock);
928 
929     return info_changed;
930 }
931 
mpp_buf_slot_ready(MppBufSlots slots)932 MPP_RET mpp_buf_slot_ready(MppBufSlots slots)
933 {
934     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
935 
936     if (!impl) {
937         mpp_err_f("found NULL input\n");
938         return MPP_ERR_NULL_PTR;
939     }
940 
941     buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p is ready now\n", impl);
942 
943     mpp_mutex_lock(&impl->lock);
944 
945     slot_assert(impl, impl->slots);
946     if (!impl->info_changed)
947         mpp_log("found info change ready set without internal info change\n");
948 
949     // ready mean the info_set will be copy to info as the new configuration
950     if (impl->buf_count != impl->new_count) {
951         impl->slots = mpp_realloc(impl->slots, MppBufSlotEntry, impl->new_count);
952         mpp_assert(impl->slots);
953         init_slot_entry(impl, 0, impl->new_count);
954     }
955     impl->buf_count = impl->new_count;
956 
957     mpp_frame_copy(impl->info, impl->info_set);
958 
959     if (impl->logs)
960         buf_slot_logs_reset(impl->logs);
961 
962     impl->info_changed = 0;
963     impl->info_change_slot_idx = -1;
964 
965     mpp_mutex_unlock(&impl->lock);
966 
967     return MPP_OK;
968 }
969 
mpp_buf_slot_get_size(MppBufSlots slots)970 size_t mpp_buf_slot_get_size(MppBufSlots slots)
971 {
972     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
973     size_t size = 0;
974 
975     if (!impl) {
976         mpp_err_f("found NULL input\n");
977         return 0;
978     }
979 
980     mpp_mutex_lock(&impl->lock);
981     size = impl->buf_size;
982     mpp_mutex_unlock(&impl->lock);
983 
984     return size;
985 }
986 
mpp_buf_slot_get_count(MppBufSlots slots)987 RK_S32 mpp_buf_slot_get_count(MppBufSlots slots)
988 {
989     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
990     size_t count = 0;
991 
992     if (!impl) {
993         mpp_err_f("found NULL input\n");
994         return -1;
995     }
996 
997     mpp_mutex_lock(&impl->lock);
998     count = impl->buf_count;
999     mpp_mutex_unlock(&impl->lock);
1000 
1001     return count;
1002 }
1003 
mpp_buf_slot_set_callback(MppBufSlots slots,MppCbCtx * cb_ctx)1004 MPP_RET mpp_buf_slot_set_callback(MppBufSlots slots, MppCbCtx *cb_ctx)
1005 {
1006     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1007 
1008     if (!impl) {
1009         mpp_err_f("found NULL input\n");
1010         return MPP_NOK;
1011     }
1012 
1013     mpp_mutex_lock(&impl->lock);
1014     impl->callback = *cb_ctx;
1015     mpp_mutex_unlock(&impl->lock);
1016 
1017     return MPP_OK;
1018 }
1019 
mpp_buf_slot_get_unused(MppBufSlots slots,RK_S32 * index)1020 MPP_RET mpp_buf_slot_get_unused(MppBufSlots slots, RK_S32 *index)
1021 {
1022     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1023     MppBufSlotEntry *slot;
1024     RK_S32 i;
1025 
1026     if (!impl || !index) {
1027         mpp_err_f("found NULL input\n");
1028         return MPP_ERR_NULL_PTR;
1029     }
1030 
1031     slot = impl->slots;
1032 
1033     mpp_mutex_lock(&impl->lock);
1034 
1035     for (i = 0; i < impl->buf_count; i++, slot++) {
1036         if (!slot->status.on_used) {
1037             *index = i;
1038             slot_ops_with_log(impl, slot, SLOT_SET_ON_USE, NULL);
1039             slot_ops_with_log(impl, slot, SLOT_SET_NOT_READY, NULL);
1040             impl->used_count++;
1041             mpp_mutex_unlock(&impl->lock);
1042             return MPP_OK;
1043         }
1044     }
1045 
1046     *index = -1;
1047     mpp_err_f("failed to get a unused slot\n");
1048     dump_slots(impl);
1049     slot_assert(impl, 0);
1050 
1051     mpp_mutex_unlock(&impl->lock);
1052 
1053     return MPP_NOK;
1054 }
1055 
mpp_buf_slot_set_flag(MppBufSlots slots,RK_S32 index,SlotUsageType type)1056 MPP_RET mpp_buf_slot_set_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type)
1057 {
1058     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1059 
1060     if (!impl) {
1061         mpp_err_f("found NULL input\n");
1062         return MPP_ERR_NULL_PTR;
1063     }
1064 
1065     mpp_mutex_lock(&impl->lock);
1066 
1067     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1068     slot_ops_with_log(impl, &impl->slots[index], set_flag_op[type], NULL);
1069 
1070     mpp_mutex_unlock(&impl->lock);
1071 
1072     return MPP_OK;
1073 }
1074 
mpp_buf_slot_clr_flag(MppBufSlots slots,RK_S32 index,SlotUsageType type)1075 MPP_RET mpp_buf_slot_clr_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type)
1076 {
1077     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1078     MppBufSlotEntry *slot;
1079     RK_S32 unused = 0;
1080 
1081     if (!impl) {
1082         mpp_err_f("found NULL input\n");
1083         return MPP_ERR_NULL_PTR;
1084     }
1085 
1086     mpp_mutex_lock(&impl->lock);
1087 
1088     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1089     slot = &impl->slots[index];
1090     slot_ops_with_log(impl, slot, clr_flag_op[type], NULL);
1091 
1092     if (type == SLOT_HAL_OUTPUT)
1093         impl->decode_count++;
1094 
1095     unused = check_entry_unused(impl, slot);
1096 
1097     mpp_mutex_unlock(&impl->lock);
1098 
1099     if (unused)
1100         mpp_callback(&impl->callback, impl);
1101     return MPP_OK;
1102 }
1103 
mpp_buf_slot_enqueue(MppBufSlots slots,RK_S32 index,SlotQueueType type)1104 MPP_RET mpp_buf_slot_enqueue(MppBufSlots slots, RK_S32 index, SlotQueueType type)
1105 {
1106     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1107     MppBufSlotEntry *slot;
1108 
1109     if (!impl) {
1110         mpp_err_f("found NULL input\n");
1111         return MPP_ERR_NULL_PTR;
1112     }
1113 
1114     mpp_mutex_lock(&impl->lock);
1115 
1116     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1117     slot = &impl->slots[index];
1118     slot_ops_with_log(impl, slot, (MppBufSlotOps)(SLOT_ENQUEUE + type), NULL);
1119 
1120     // add slot to display list
1121     list_del_init(&slot->list);
1122     list_add_tail(&slot->list, &impl->queue[type]);
1123 
1124     mpp_mutex_unlock(&impl->lock);
1125 
1126     return MPP_OK;
1127 }
1128 
mpp_buf_slot_dequeue(MppBufSlots slots,RK_S32 * index,SlotQueueType type)1129 MPP_RET mpp_buf_slot_dequeue(MppBufSlots slots, RK_S32 *index, SlotQueueType type)
1130 {
1131     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1132     MppBufSlotEntry *slot;
1133 
1134     if (!impl || !index) {
1135         mpp_err_f("found NULL input\n");
1136         return MPP_ERR_NULL_PTR;
1137     }
1138 
1139     mpp_mutex_lock(&impl->lock);
1140 
1141     if (list_empty(&impl->queue[type])) {
1142         mpp_mutex_unlock(&impl->lock);
1143         return MPP_NOK;
1144     }
1145 
1146     slot = list_entry(impl->queue[type].next, MppBufSlotEntry, list);
1147     if (slot->status.not_ready) {
1148         mpp_mutex_unlock(&impl->lock);
1149         return MPP_NOK;
1150     }
1151 
1152     // make sure that this slot is just the next display slot
1153     list_del_init(&slot->list);
1154     slot_assert(impl, slot->index < impl->buf_count);
1155     slot_ops_with_log(impl, slot, (MppBufSlotOps)(SLOT_DEQUEUE + type), NULL);
1156     impl->display_count++;
1157     *index = slot->index;
1158 
1159     mpp_mutex_unlock(&impl->lock);
1160 
1161     return MPP_OK;
1162 }
1163 
mpp_buf_slot_set_prop(MppBufSlots slots,RK_S32 index,SlotPropType type,void * val)1164 MPP_RET mpp_buf_slot_set_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val)
1165 {
1166     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1167     MppBufSlotEntry *slot;
1168 
1169     if (!impl || !val || type >= SLOT_PROP_BUTT) {
1170         mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
1171         return MPP_ERR_UNKNOW;
1172     }
1173 
1174     mpp_mutex_lock(&impl->lock);
1175 
1176     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1177     slot = &impl->slots[index];
1178     slot_ops_with_log(impl, slot, set_val_op[type], val);
1179 
1180     switch (type) {
1181     case SLOT_EOS: {
1182         RK_U32 eos = *(RK_U32*)val;
1183 
1184         slot->eos = eos;
1185         if (slot->frame)
1186             mpp_frame_set_eos(slot->frame, eos);
1187     } break;
1188     case SLOT_FRAME: {
1189         MppFrame frame = val;
1190         MppFrameImpl *src;
1191         MppFrameImpl *dst;
1192 
1193         slot_assert(impl, slot->status.not_ready);
1194         /*
1195          * we need to detect infomation change here
1196          * there are two types of info change:
1197          * 1. buffer size change
1198          *    this case need to reset buffer group and commit buffer with new size
1199          * 2. display info change
1200          *    if only width/height/fmt is change and buffer do not need to be reset
1201          *    only display info change is need
1202          */
1203         generate_info_set(impl, frame, 0);
1204 
1205         if (!slot->frame)
1206             mpp_frame_init(&slot->frame);
1207 
1208         src = (MppFrameImpl *)frame;
1209         dst = (MppFrameImpl *)slot->frame;
1210         mpp_frame_copy(dst, src);
1211         // NOTE: stride from codec need to be change to hal stride
1212         //       hor_stride and ver_stride can not be zero
1213         //       they are the stride required by codec
1214         //       then hal will modify it according to hardware requirement
1215         mpp_assert(src->hor_stride);
1216         mpp_assert(src->ver_stride);
1217         dst->hor_stride = src->hor_stride;
1218         dst->ver_stride = src->ver_stride;
1219         dst->eos = slot->eos;
1220 
1221         if (mpp_frame_info_cmp(impl->info, impl->info_set)) {
1222             MppFrameImpl *old = (MppFrameImpl *)impl->info;
1223 
1224             impl->info_changed = 1;
1225             impl->info_change_slot_idx = index;
1226 
1227             if (impl->coding_type != MPP_VIDEO_CodingMJPEG)
1228                 impl->align_chk_log_en = impl->align_chk_log_env;
1229 
1230             if (old->width || old->height) {
1231                 mpp_dbg_info("info change found\n");
1232                 mpp_dbg_info("old width %4d height %4d stride hor %4d ver %4d fmt %4d\n",
1233                              old->width, old->height, old->hor_stride,
1234                              old->ver_stride, old->fmt);
1235             }
1236             mpp_dbg_info("new width %4d height %4d stride hor %4d ver %4d fmt %4d\n",
1237                          dst->width, dst->height, dst->hor_stride, dst->ver_stride,
1238                          dst->fmt);
1239             // info change found here
1240         }
1241     } break;
1242     case SLOT_BUFFER: {
1243         MppBuffer buffer = val;
1244 
1245         if (slot->buffer) {
1246             // NOTE: reset buffer only on stream buffer slot
1247             slot_assert(impl, !slot->frame);
1248             mpp_buffer_put(slot->buffer);
1249         }
1250         mpp_buffer_inc_ref(buffer);
1251         slot->buffer = buffer;
1252 
1253         if (slot->frame)
1254             mpp_frame_set_buffer(slot->frame, buffer);
1255     } break;
1256     default : {
1257     } break;
1258     }
1259 
1260     mpp_mutex_unlock(&impl->lock);
1261 
1262     return MPP_OK;
1263 }
1264 
mpp_buf_slot_get_prop(MppBufSlots slots,RK_S32 index,SlotPropType type,void * val)1265 MPP_RET mpp_buf_slot_get_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val)
1266 {
1267     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1268     MppBufSlotEntry *slot;
1269 
1270     if (!impl || !val || type >= SLOT_PROP_BUTT) {
1271         mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
1272         return MPP_ERR_UNKNOW;
1273     }
1274 
1275     mpp_mutex_lock(&impl->lock);
1276 
1277     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1278     slot = &impl->slots[index];
1279 
1280     switch (type) {
1281     case SLOT_EOS: {
1282         *(RK_U32*)val = slot->eos;
1283     } break;
1284     case SLOT_FRAME: {
1285         MppFrame *frame = (MppFrame *)val;
1286         //*frame = (slot->status.has_frame) ? (slot->frame) : (NULL);
1287 
1288         mpp_assert(slot->status.has_frame);
1289         if (slot->status.has_frame) {
1290             if (!*frame )
1291                 mpp_frame_init(frame);
1292             if (*frame)
1293                 mpp_frame_copy(*frame, slot->frame);
1294         } else
1295             *frame = NULL;
1296     } break;
1297     case SLOT_FRAME_PTR: {
1298         MppFrame *frame = (MppFrame *)val;
1299 
1300         mpp_assert(slot->status.has_frame);
1301         *frame = (slot->status.has_frame) ? (slot->frame) : (NULL);
1302     } break;
1303     case SLOT_BUFFER: {
1304         MppBuffer *buffer = (MppBuffer *)val;
1305 
1306         *buffer = (slot->status.has_buffer) ? (slot->buffer) : (NULL);
1307     } break;
1308     default : {
1309     } break;
1310     }
1311 
1312     mpp_mutex_unlock(&impl->lock);
1313 
1314     return MPP_OK;
1315 }
1316 
mpp_buf_slot_reset(MppBufSlots slots,RK_S32 index)1317 MPP_RET mpp_buf_slot_reset(MppBufSlots slots, RK_S32 index)
1318 {
1319     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1320     MppBufSlotEntry *slot;
1321 
1322     if (!impl || index < 0) {
1323         mpp_err_f("found NULL input\n");
1324         return MPP_ERR_NULL_PTR;
1325     }
1326 
1327     buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p reset index %d\n", slots, index);
1328 
1329     mpp_mutex_lock(&impl->lock);
1330 
1331     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1332     slot = &impl->slots[index];
1333 
1334     // make sure that this slot is just the next display slot
1335     list_del_init(&slot->list);
1336     slot_ops_with_log(impl, slot, SLOT_CLR_QUEUE_USE, NULL);
1337     slot_ops_with_log(impl, slot, SLOT_DEQUEUE, NULL);
1338     slot_ops_with_log(impl, slot, SLOT_CLR_ON_USE, NULL);
1339 
1340     mpp_mutex_unlock(&impl->lock);
1341 
1342     return MPP_OK;
1343 }
1344 
mpp_buf_slot_default_info(MppBufSlots slots,RK_S32 index,void * val)1345 MPP_RET mpp_buf_slot_default_info(MppBufSlots slots, RK_S32 index, void *val)
1346 {
1347     if (!slots || index < 0) {
1348         mpp_err_f("found NULL input\n");
1349         return MPP_ERR_NULL_PTR;
1350     }
1351 
1352     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1353     mpp_mutex_lock(&impl->lock);
1354     slot_assert(impl, (index >= 0) && (index < impl->buf_count));
1355     MppBufSlotEntry *slot = &impl->slots[index];
1356 
1357     slot_assert(impl, slot->status.not_ready);
1358     slot_assert(impl, !slot->frame);
1359     slot_assert(impl, impl->info_set);
1360 
1361     if (!slot->frame) {
1362         mpp_frame_init(&slot->frame);
1363         mpp_frame_copy(slot->frame, impl->info_set);
1364     }
1365 
1366     MppFrame *frame = (MppFrame *)val;
1367     *frame = slot->frame;
1368 
1369     slot_ops_with_log(impl, slot, SLOT_CLR_NOT_READY, NULL);
1370     slot_ops_with_log(impl, slot, SLOT_SET_FRAME, slot->frame);
1371     mpp_mutex_unlock(&impl->lock);
1372 
1373     return MPP_OK;
1374 }
1375 
mpp_slots_is_empty(MppBufSlots slots,SlotQueueType type)1376 RK_U32 mpp_slots_is_empty(MppBufSlots slots, SlotQueueType type)
1377 {
1378     RK_U32 is_empty = 0;
1379     if (!slots) {
1380         mpp_err_f("found NULL input\n");
1381         return 0;
1382     }
1383 
1384     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1385     mpp_mutex_lock(&impl->lock);
1386     is_empty = list_empty(&impl->queue[type]) ? 1 : 0;
1387     mpp_mutex_unlock(&impl->lock);
1388 
1389     return is_empty;
1390 }
1391 
mpp_slots_get_used_count(MppBufSlots slots)1392 RK_S32 mpp_slots_get_used_count(MppBufSlots slots)
1393 {
1394     RK_S32 used_count = 0;
1395     if (!slots) {
1396         mpp_err_f("found NULL input\n");
1397         return 0;
1398     }
1399     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1400     mpp_mutex_lock(&impl->lock);
1401     used_count = impl->used_count;
1402     mpp_mutex_unlock(&impl->lock);
1403 
1404     return used_count;
1405 }
1406 
mpp_slots_get_unused_count(MppBufSlots slots)1407 RK_S32 mpp_slots_get_unused_count(MppBufSlots slots)
1408 {
1409     RK_S32 unused_count = 0;
1410     if (!slots) {
1411         mpp_err_f("found NULL input\n");
1412         return MPP_ERR_NULL_PTR;
1413     }
1414 
1415     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1416     mpp_mutex_lock(&impl->lock);
1417     slot_assert(impl, (impl->used_count >= 0) && (impl->used_count <= impl->buf_count));
1418     unused_count = impl->buf_count - impl->used_count;
1419     mpp_mutex_unlock(&impl->lock);
1420 
1421     return unused_count;
1422 }
1423 
mpp_slots_set_prop(MppBufSlots slots,SlotsPropType type,void * val)1424 MPP_RET mpp_slots_set_prop(MppBufSlots slots, SlotsPropType type, void *val)
1425 {
1426     if (!slots || !val || type >= SLOTS_PROP_BUTT) {
1427         mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
1428         return MPP_ERR_UNKNOW;
1429     }
1430 
1431     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1432     mpp_mutex_lock(&impl->lock);
1433     RK_U32 value = *((RK_U32*)val);
1434     switch (type) {
1435     case SLOTS_EOS: {
1436         impl->eos = value;
1437     } break;
1438     case SLOTS_NUMERATOR : {
1439         impl->numerator = value;
1440     } break;
1441     case SLOTS_DENOMINATOR : {
1442         impl->denominator = value;
1443     } break;
1444     case SLOTS_HOR_ALIGN: {
1445         impl->hal_hor_align = (AlignFunc)val;
1446     } break;
1447     case SLOTS_VER_ALIGN: {
1448         impl->hal_ver_align = (AlignFunc)val;
1449     } break;
1450     case SLOTS_LEN_ALIGN: {
1451         impl->hal_len_align = (AlignFunc)val;
1452     } break;
1453     case SLOTS_COUNT: {
1454         impl->buf_count = value;
1455     } break;
1456     case SLOTS_SIZE: {
1457         impl->buf_size = value;
1458     } break;
1459     case SLOTS_FRAME_INFO: {
1460         // do info change detection here
1461         generate_info_set(impl, (MppFrame)val, 1);
1462         mpp_frame_copy(impl->info, impl->info_set);
1463         {
1464             MppFrameImpl *p = (MppFrameImpl *)impl->info;
1465             mpp_log("set frame info: w %4d h %4d hor %4d ver %4d\n", p->width, p->height, p->hor_stride, p->ver_stride);
1466         }
1467         mpp_frame_copy((MppFrame)val, impl->info_set);
1468         if (impl->info_change_slot_idx >= 0) {
1469             MppBufSlotEntry *slot = &impl->slots[impl->info_change_slot_idx];
1470 
1471             if (slot->frame) {
1472                 MppFrameImpl *dst = (MppFrameImpl *)slot->frame;
1473                 MppFrameImpl *src = (MppFrameImpl *)val;
1474 
1475                 dst->fmt = src->fmt;
1476                 dst->hor_stride = src->hor_stride;
1477                 dst->hor_stride_pixel = src->hor_stride_pixel;
1478                 dst->ver_stride = src->ver_stride;
1479                 dst->buf_size = src->buf_size;
1480 
1481                 if (MPP_FRAME_FMT_IS_FBC(dst->fmt) && impl->hal_fbc_adj_cfg.func)
1482                     impl->hal_fbc_adj_cfg.func(impl, dst, impl->hal_fbc_adj_cfg.expand);
1483             }
1484 
1485             impl->info_change_slot_idx = -1;
1486         }
1487     } break;
1488     case SLOTS_HAL_FBC_ADJ : {
1489         impl->hal_fbc_adj_cfg = *((SlotHalFbcAdjCfg *)val);
1490     } break;
1491     case SLOTS_CODING_TYPE : {
1492         impl->coding_type = *((MppCodingType *)val);
1493     } break;
1494     case SLOTS_WIDTH_ALIGN: {
1495         impl->hal_width_align = (AlignFunc)val;
1496     } break;
1497     default : {
1498     } break;
1499     }
1500     mpp_mutex_unlock(&impl->lock);
1501 
1502     return MPP_OK;
1503 }
1504 
mpp_slots_get_prop(MppBufSlots slots,SlotsPropType type,void * val)1505 MPP_RET mpp_slots_get_prop(MppBufSlots slots, SlotsPropType type, void *val)
1506 {
1507     if (!slots || !val || type >= SLOTS_PROP_BUTT) {
1508         mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
1509         return MPP_NOK;
1510     }
1511 
1512     MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
1513     mpp_mutex_lock(&impl->lock);
1514     MPP_RET ret = MPP_OK;
1515 
1516     switch (type) {
1517     case SLOTS_EOS: {
1518         *((RK_U32 *)val) = impl->eos;
1519     } break;
1520     case SLOTS_COUNT: {
1521         *((RK_U32 *)val) = impl->buf_count;
1522     } break;
1523     case SLOTS_SIZE: {
1524         *((RK_U32 *)val) = (RK_U32)impl->buf_size;
1525     } break;
1526     case SLOTS_FRAME_INFO: {
1527         MppFrame frame = (MppFrame)val;
1528         MppFrame info  = impl->info;
1529         mpp_frame_copy(frame, info);
1530     } break;
1531     default : {
1532         mpp_err("can not get slots prop type %d\n", type);
1533         ret = MPP_NOK;
1534     } break;
1535     }
1536     mpp_mutex_unlock(&impl->lock);
1537 
1538     return ret;
1539 }
1540