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