mpp_enc_roi_utils.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. /*
  2. * Copyright 2021 Rockchip Electronics Co. LTD
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define MODULE_TAG "enc_roi_utils"
  17. #include <string.h>
  18. #include "rk_type.h"
  19. #include "mpp_env.h"
  20. #include "mpp_mem.h"
  21. #include "mpp_soc.h"
  22. #include "mpp_common.h"
  23. #include "mpp_debug.h"
  24. #include "mpp_enc_roi_utils.h"
  25. #define VEPU541_MAX_ROI_NUM 8
  26. #define CU_BASE_CFG_BYTE 64
  27. #define CU_QP_CFG_BYTE 192
  28. typedef enum RoiType_e {
  29. ROI_TYPE_AUTO = -2,
  30. ROI_TYPE_NONE = -1,
  31. ROI_TYPE_0 = 0, /* vepu roi, not support yet */
  32. ROI_TYPE_1 = 1, /* rv1109/rk3566/rk3568 roi */
  33. ROI_TYPE_2 = 2, /* rk3588 roi */
  34. /* legacy */
  35. ROI_TYPE_LEGACY = 0x10, /* legacy region config way */
  36. ROI_TYPE_BUTT,
  37. } RoiType;
  38. typedef struct Vepu541RoiCfg_t {
  39. /*
  40. * Force_intra
  41. * 1 - The corresponding 16x16cu is forced to be intra
  42. * 0 - Not force to intra
  43. */
  44. RK_U16 force_intra : 1;
  45. RK_U16 reserved : 3;
  46. /*
  47. * Qp area index
  48. * The choosed qp area index.
  49. */
  50. RK_U16 qp_area_idx : 3;
  51. /*
  52. * Area qp limit function enable flag
  53. * Force to be true in vepu541
  54. */
  55. RK_U16 qp_area_en : 1;
  56. /*
  57. * Qp_adj
  58. * Qp_adj
  59. * in absolute qp mode qp_adj is the final qp used by encoder
  60. * in relative qp mode qp_adj is a adjustment to final qp
  61. */
  62. RK_S16 qp_adj : 7;
  63. /*
  64. * Qp_adj_mode
  65. * Qp adjustment mode
  66. * 1 - absolute qp mode:
  67. * the 16x16 MB qp is set to the qp_adj value
  68. * 0 - relative qp mode
  69. * the 16x16 MB qp is adjusted by qp_adj value
  70. */
  71. RK_U16 qp_adj_mode : 1;
  72. } Vepu541RoiCfg;
  73. typedef struct Vepu580RoiH264BsCfg_t {
  74. RK_U64 force_inter : 42;
  75. RK_U64 mode_mask : 9;
  76. RK_U64 reserved : 10;
  77. RK_U64 force_intra : 1;
  78. RK_U64 qp_adj_en : 1;
  79. RK_U64 amv_en : 1;
  80. } Vepu580RoiH264BsCfg;
  81. typedef struct Vepu580RoiH265BsCfg_t {
  82. RK_U8 amv_en : 1;
  83. RK_U8 qp_adj : 1;
  84. RK_U8 force_split : 1;
  85. RK_U8 force_intra : 2;
  86. RK_U8 force_inter : 2;
  87. } Vepu580RoiH265BsCfg;
  88. typedef struct Vepu580RoiQpCfg_t {
  89. RK_U16 reserved : 4;
  90. /*
  91. * Qp area index
  92. * The choosed qp area index.
  93. */
  94. RK_U16 qp_area_idx : 4;
  95. /*
  96. * Qp_adj
  97. * Qp_adj
  98. * in absolute qp mode qp_adj is the final qp used by encoder
  99. * in relative qp mode qp_adj is a adjustment to final qp
  100. */
  101. RK_S16 qp_adj : 7;
  102. /*
  103. * Qp_adj_mode
  104. * Qp adjustment mode
  105. * 1 - absolute qp mode:
  106. * the 16x16 MB qp is set to the qp_adj value
  107. * 0 - relative qp mode
  108. * the 16x16 MB qp is adjusted by qp_adj value
  109. */
  110. RK_U16 qp_adj_mode : 1;
  111. } Vepu580RoiQpCfg;
  112. typedef struct MppEncRoiImpl_t {
  113. /* common parameters */
  114. RK_S32 w;
  115. RK_S32 h;
  116. MppCodingType type;
  117. /* region config set */
  118. RoiRegionCfg *regions;
  119. RK_S32 max_count;
  120. RK_S32 count;
  121. /*
  122. * roi_type is for the different encoder roi config
  123. *
  124. * 0 - rv1109/rk3566/rk3568 roi
  125. * 1 - rk3588 roi
  126. *
  127. * others - legacy roi config
  128. */
  129. RoiType roi_type;
  130. /* For roi type legacy config */
  131. MppEncROICfg legacy_roi_cfg;
  132. MppEncROIRegion *legacy_roi_region;
  133. /* For roi type 1&2 config */
  134. MppBufferGroup roi_grp;
  135. MppEncROICfg2 roi_cfg;
  136. /* buffer address and size of MppBuffer in MppEncROICfg2 */
  137. void *dst_base;
  138. void *dst_qp;
  139. void *dst_amv;
  140. void *dst_mv;
  141. RK_U32 base_cfg_size;
  142. RK_U32 qp_cfg_size;
  143. RK_U32 amv_cfg_size;
  144. RK_U32 mv_cfg_size;
  145. RK_U8 *cu_map;
  146. RK_U32 cu_size;
  147. /* tmp buffer for convert vepu54x roi cfg to vepu58x roi cfg */
  148. Vepu541RoiCfg *tmp;
  149. } MppEncRoiImpl;
  150. static RK_U32 raster2scan8[64] = {
  151. 0, 1, 4, 5, 16, 17, 20, 21,
  152. 2, 3, 6, 7, 18, 19, 22, 23,
  153. 8, 9, 12, 13, 24, 25, 28, 29,
  154. 10, 11, 14, 15, 26, 27, 30, 31,
  155. 32, 33, 36, 37, 48, 49, 52, 53,
  156. 34, 35, 38, 39, 50, 51, 54, 55,
  157. 40, 41, 44, 45, 56, 57, 60, 61,
  158. 42, 43, 46, 47, 58, 59, 62, 63
  159. };
  160. static RK_U32 raster2zscan16[16] = {
  161. 0, 1, 4, 5,
  162. 2, 3, 6, 7,
  163. 8, 9, 12, 13,
  164. 10, 11, 14, 15
  165. };
  166. static MPP_RET vepu54x_h265_set_roi(void *dst_buf, void *src_buf, RK_S32 w, RK_S32 h)
  167. {
  168. Vepu541RoiCfg *src = (Vepu541RoiCfg *)src_buf;
  169. Vepu541RoiCfg *dst = (Vepu541RoiCfg *)dst_buf;
  170. RK_S32 mb_w = MPP_ALIGN(w, 64) / 64;
  171. RK_S32 mb_h = MPP_ALIGN(h, 64) / 64;
  172. RK_S32 ctu_line = mb_w;
  173. RK_S32 j;
  174. for (j = 0; j < mb_h; j++) {
  175. RK_S32 i;
  176. for (i = 0; i < mb_w; i++) {
  177. RK_S32 ctu_addr = j * ctu_line + i;
  178. RK_S32 cu16_num_line = ctu_line * 4;
  179. RK_S32 cu16cnt;
  180. for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
  181. RK_S32 cu16_addr_in_frame;
  182. RK_S32 cu16_x = cu16cnt % 4;
  183. RK_S32 cu16_y = cu16cnt / 4;
  184. cu16_x += i * 4;
  185. cu16_y += j * 4;
  186. cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
  187. dst[ctu_addr * 16 + cu16cnt] = src[cu16_addr_in_frame];
  188. }
  189. }
  190. }
  191. return MPP_OK;
  192. }
  193. static MPP_RET gen_vepu54x_roi(MppEncRoiImpl *ctx, Vepu541RoiCfg *dst)
  194. {
  195. RoiRegionCfg *region = ctx->regions;
  196. RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
  197. RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
  198. RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
  199. RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
  200. Vepu541RoiCfg cfg;
  201. MPP_RET ret = MPP_NOK;
  202. RK_S32 i;
  203. memset(ctx->cu_map, 0, ctx->cu_size);
  204. cfg.force_intra = 0;
  205. cfg.reserved = 0;
  206. cfg.qp_area_idx = 0;
  207. cfg.qp_area_en = 1;
  208. cfg.qp_adj = 0;
  209. cfg.qp_adj_mode = 0;
  210. /* step 1. reset all the config */
  211. for (i = 0; i < stride_h * stride_v; i++)
  212. memcpy(dst + i, &cfg, sizeof(cfg));
  213. if (ctx->w <= 0 || ctx->h <= 0) {
  214. mpp_err_f("invalid size [%d:%d]\n", ctx->w, ctx->h);
  215. goto DONE;
  216. }
  217. /* check region config */
  218. ret = MPP_OK;
  219. for (i = 0; i < ctx->count; i++, region++) {
  220. if (region->x + region->w > ctx->w || region->y + region->h > ctx->h)
  221. ret = MPP_NOK;
  222. if (region->force_intra > 1 || region->qp_mode > 1)
  223. ret = MPP_NOK;
  224. if ((region->qp_mode && region->qp_val > 51) ||
  225. (!region->qp_mode && (region->qp_val > 51 || region->qp_val < -51)))
  226. ret = MPP_NOK;
  227. if (ret) {
  228. mpp_err_f("region %d invalid param:\n", i);
  229. mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n",
  230. region->x, region->y, region->w, region->h, ctx->w, ctx->h);
  231. mpp_err_f("force intra %d qp mode %d val %d\n",
  232. region->force_intra, region->qp_mode, region->qp_val);
  233. goto DONE;
  234. }
  235. }
  236. region = ctx->regions;
  237. /* step 2. setup region for top to bottom */
  238. for (i = 0; i < ctx->count; i++, region++) {
  239. Vepu541RoiCfg *p = dst;
  240. RK_U8 *map = ctx->cu_map;
  241. RK_S32 roi_width = (region->w + 15) / 16;
  242. RK_S32 roi_height = (region->h + 15) / 16;
  243. RK_S32 pos_x_init = (region->x + 15) / 16;
  244. RK_S32 pos_y_init = (region->y + 15) / 16;
  245. RK_S32 pos_x_end = pos_x_init + roi_width;
  246. RK_S32 pos_y_end = pos_y_init + roi_height;
  247. RK_S32 x, y;
  248. mpp_assert(pos_x_init >= 0 && pos_x_init < mb_w);
  249. mpp_assert(pos_x_end >= 0 && pos_x_end <= mb_w);
  250. mpp_assert(pos_y_init >= 0 && pos_y_init < mb_h);
  251. mpp_assert(pos_y_end >= 0 && pos_y_end <= mb_h);
  252. cfg.force_intra = region->force_intra;
  253. cfg.reserved = 0;
  254. cfg.qp_area_idx = 0;
  255. // NOTE: When roi is enabled the qp_area_en should be one.
  256. cfg.qp_area_en = 1; // region->area_map_en;
  257. cfg.qp_adj = region->qp_val;
  258. cfg.qp_adj_mode = region->qp_mode;
  259. p += pos_y_init * stride_h + pos_x_init;
  260. map += pos_y_init * stride_h + pos_x_init;
  261. for (y = 0; y < roi_height; y++) {
  262. for (x = 0; x < roi_width; x++) {
  263. memcpy(p + x, &cfg, sizeof(cfg));
  264. if (ctx->type == MPP_VIDEO_CodingAVC) {
  265. *(map + x) = 1;
  266. }
  267. }
  268. p += stride_h;
  269. map += stride_h;
  270. }
  271. if (ctx->type == MPP_VIDEO_CodingHEVC) {
  272. map = ctx->cu_map;
  273. RK_U32 stride_cu64_h = stride_h * 16 / 64;
  274. roi_width = (region->w + 64) / 64;
  275. roi_height = (region->h + 64) / 64;
  276. if (region->x < 64) {
  277. pos_x_init = 0;
  278. roi_width += 2;
  279. } else if (region->x % 64) {
  280. pos_x_init = (region->x - 64) / 64;
  281. roi_width += 2;
  282. } else
  283. pos_x_init = region->x / 64;
  284. if (region->y < 64) {
  285. pos_y_init = 0;
  286. roi_height += 2;
  287. } else if (region->y % 64) {
  288. pos_y_init = (region->y - 64) / 64;
  289. roi_height += 2;
  290. } else
  291. pos_y_init = region->y / 64;
  292. map += pos_y_init * stride_cu64_h + pos_x_init;
  293. for (y = 0; y < roi_height; y++) {
  294. for (x = 0; x < roi_width; x++) {
  295. *(map + x) = 1;
  296. }
  297. map += stride_cu64_h;
  298. }
  299. }
  300. }
  301. DONE:
  302. return ret;
  303. }
  304. static MPP_RET set_roi_pos_val(RK_U32 *buf, RK_U32 pos, RK_U32 value)
  305. {
  306. RK_U32 index = pos / 32;
  307. RK_U32 bits = pos % 32;
  308. buf[index] = buf[index] | (value << bits);
  309. return MPP_OK;
  310. }
  311. #define set_roi_qpadj(buf, index, val) \
  312. do { \
  313. RK_U32 offset = 425 + index; \
  314. set_roi_pos_val(buf, offset, val); \
  315. } while(0)
  316. #define set_roi_force_split(buf, index, val) \
  317. do { \
  318. RK_U32 offset = 340 + index; \
  319. set_roi_pos_val(buf, offset, val); \
  320. } while(0)
  321. #define set_roi_force_intra(buf, index, val) \
  322. do { \
  323. RK_U32 offset = 170 + index * 2; \
  324. set_roi_pos_val(buf, offset, val); \
  325. } while(0)
  326. #define set_roi_force_inter(buf, index, val) \
  327. do { \
  328. RK_U32 offset = index * 2; \
  329. set_roi_pos_val(buf, offset, val); \
  330. } while(0)
  331. static void set_roi_cu8_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
  332. {
  333. set_roi_qpadj(buf, index, val.qp_adj);
  334. set_roi_force_split(buf, index, val.force_split);
  335. set_roi_force_intra(buf, index, val.force_intra);
  336. set_roi_force_inter(buf, index, val.force_inter);
  337. }
  338. static void set_roi_cu16_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
  339. {
  340. index += 64;
  341. set_roi_qpadj(buf, index, val.qp_adj);
  342. set_roi_force_split(buf, index, val.force_split);
  343. set_roi_force_intra(buf, index, val.force_intra);
  344. set_roi_force_inter(buf, index, val.force_inter);
  345. }
  346. static void set_roi_cu32_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
  347. {
  348. index += 80;
  349. set_roi_qpadj(buf, index, val.qp_adj);
  350. set_roi_force_split(buf, index, val.force_split);
  351. set_roi_force_intra(buf, index, val.force_intra);
  352. set_roi_force_inter(buf, index, val.force_inter);
  353. }
  354. static void set_roi_cu64_base_cfg(RK_U32 *buf, Vepu580RoiH265BsCfg val)
  355. {
  356. set_roi_qpadj(buf, 84, val.qp_adj);
  357. set_roi_force_split(buf, 84, val.force_split);
  358. set_roi_force_intra(buf, 84, val.force_intra);
  359. set_roi_force_inter(buf, 84, val.force_inter);
  360. }
  361. static void set_roi_qp_cfg(void *buf, RK_U32 index, Vepu541RoiCfg *cfg)
  362. {
  363. Vepu580RoiQpCfg *qp_cfg_base = (Vepu580RoiQpCfg *)buf;
  364. Vepu580RoiQpCfg *qp_cfg = &qp_cfg_base[index];
  365. qp_cfg->qp_adj = cfg->qp_adj;
  366. qp_cfg->qp_adj_mode = cfg->qp_adj_mode;
  367. qp_cfg->qp_area_idx = cfg->qp_area_idx;
  368. }
  369. #define set_roi_cu8_qp_cfg(buf, index, cfg) \
  370. do { \
  371. RK_U32 offset = index; \
  372. set_roi_qp_cfg(buf, offset, cfg); \
  373. } while(0)
  374. #define set_roi_cu16_qp_cfg(buf, index, cfg) \
  375. do { \
  376. RK_U32 offset = 64 + index; \
  377. set_roi_qp_cfg(buf, offset, cfg); \
  378. } while(0)
  379. #define set_roi_cu32_qp_cfg(buf, index, cfg) \
  380. do { \
  381. RK_U32 offset = 80 + index; \
  382. set_roi_qp_cfg(buf, offset, cfg); \
  383. } while(0)
  384. #define set_roi_cu64_qp_cfg(buf, cfg) \
  385. do { \
  386. RK_U32 offset = 84; \
  387. set_roi_qp_cfg(buf, offset, cfg); \
  388. } while(0)
  389. void set_roi_amv(RK_U32 *buf, Vepu580RoiH265BsCfg val)
  390. {
  391. set_roi_pos_val(buf, 511, val.amv_en);
  392. }
  393. static MPP_RET gen_vepu580_roi_h264(MppEncRoiImpl *ctx)
  394. {
  395. RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
  396. RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
  397. RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
  398. RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
  399. RK_S32 roi_buf_size = stride_h * stride_v * 8;
  400. RK_S32 roi_qp_size = stride_h * stride_v * 2;
  401. Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
  402. Vepu580RoiQpCfg *dst_qp = ctx->dst_qp;
  403. Vepu580RoiH264BsCfg *dst_base = ctx->dst_base;
  404. RK_S32 j, k;
  405. if (!src || !dst_qp || !dst_base)
  406. return MPP_NOK;
  407. memset(dst_base, 0, roi_buf_size);
  408. memset(dst_qp, 0, roi_qp_size);
  409. for (j = 0; j < mb_h; j++) {
  410. for (k = 0; k < stride_h; k++) {
  411. if (ctx->cu_map[j * stride_h + k]) {
  412. Vepu541RoiCfg *cu_cfg = &src[j * stride_h + k];
  413. Vepu580RoiQpCfg *qp_cfg = &dst_qp[j * stride_h + k];
  414. Vepu580RoiH264BsCfg *base_cfg = &dst_base[j * stride_h + k];
  415. qp_cfg->qp_adj = cu_cfg->qp_adj;
  416. qp_cfg->qp_adj_mode = cu_cfg->qp_adj_mode;
  417. qp_cfg->qp_area_idx = cu_cfg->qp_area_idx;
  418. base_cfg->force_intra = cu_cfg->force_intra;
  419. base_cfg->qp_adj_en = !!cu_cfg->qp_adj;
  420. #if 0
  421. if (j < 8 && k < 8) {
  422. RK_U64 *tmp = (RK_U64 *)base_cfg;
  423. RK_U16 *qp = (RK_U16 *)qp_cfg;
  424. mpp_log("force_intra %d, qp_adj_en %d qp_adj %d, qp_adj_mode %d",
  425. base_cfg->force_intra, base_cfg->qp_adj_en, qp_cfg->qp_adj, qp_cfg->qp_adj_mode);
  426. mpp_log("val low %8x hight %8x", *tmp & 0xffffffff, ((*tmp >> 32) & 0xffffffff));
  427. mpp_log("qp cfg %4x", *qp);
  428. }
  429. #endif
  430. }
  431. }
  432. }
  433. return MPP_OK;
  434. }
  435. void set_roi_cu16_split_cu8(RK_U32 *buf, RK_U32 cu16index, Vepu580RoiH265BsCfg val)
  436. {
  437. RK_S32 cu16_x = cu16index % 4;
  438. RK_S32 cu16_y = cu16index / 4;
  439. RK_U32 cu8cnt;
  440. // mpp_log("cu16index = %d, force intra = %d, cu16_y= %d", cu16index, val.force_intra, cu16_y);
  441. for (cu8cnt = 0; cu8cnt < 4; cu8cnt++) {
  442. RK_U32 zindex = 0;
  443. RK_U32 cu8_x = cu8cnt % 2;
  444. RK_U32 cu8_y = cu8cnt / 2;
  445. RK_U32 cu8raster_index = (cu16_y * 2 + cu8_y) * 8 + cu16_x * 2 + cu8_x;
  446. // mpp_log("cu8raster_index = %d", cu8raster_index);
  447. zindex = raster2scan8[cu8raster_index];
  448. // mpp_log("cu8raster_index = %d zindex = %d x %d, y %d, cu8_x %d cu8_y %d",
  449. // cu8raster_index,zindex, x, y, cu8_x, cu8_y);
  450. set_roi_cu8_base_cfg(buf, zindex, val);
  451. }
  452. }
  453. static MPP_RET gen_vepu580_roi_h265(MppEncRoiImpl *ctx)
  454. {
  455. RK_S32 ctu_w = MPP_ALIGN(ctx->w, 64) / 64;
  456. RK_S32 ctu_h = MPP_ALIGN(ctx->h, 64) / 64;
  457. RK_S32 roi_buf_size = ctu_w * ctu_h * 64;
  458. RK_S32 roi_qp_size = ctu_w * ctu_h * 256;
  459. RK_S32 ctu_line = ctu_w;
  460. Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
  461. void *dst_qp = ctx->dst_qp;
  462. RK_U32 *dst_base = ctx->dst_base;
  463. RK_S32 i, j, k, cu16cnt;
  464. if (!src || !dst_qp || !dst_base)
  465. return MPP_NOK;
  466. // mpp_log("roi_qp_size = %d, roi_buf_size %d", roi_qp_size, roi_buf_size);
  467. memset(dst_qp, 0, roi_qp_size);
  468. memset(dst_base, 0, roi_buf_size);
  469. for (j = 0; j < ctu_h; j++) {
  470. for (k = 0; k < ctu_w; k++) {
  471. RK_S32 cu16_num_line = ctu_line * 4;
  472. RK_U32 adjust_cnt = 0;
  473. if (ctx->cu_map[j * ctu_w + k]) {
  474. for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
  475. RK_S32 cu16_x;
  476. RK_S32 cu16_y;
  477. RK_S32 cu16_addr_in_frame;
  478. RK_U32 zindex = 0;
  479. Vepu541RoiCfg *cu16_cfg = NULL;
  480. Vepu580RoiH265BsCfg val;
  481. memset(&val, 0, sizeof(val));
  482. cu16_x = cu16cnt & 3;
  483. cu16_y = cu16cnt / 4;
  484. cu16_x += k * 4;
  485. cu16_y += j * 4;
  486. cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
  487. cu16_cfg = &src[cu16_addr_in_frame];
  488. zindex = raster2zscan16[cu16cnt];
  489. val.force_intra = cu16_cfg->force_intra;
  490. val.qp_adj = !!cu16_cfg->qp_adj;
  491. if (val.force_intra || val.qp_adj) {
  492. adjust_cnt++;
  493. }
  494. set_roi_cu16_split_cu8(dst_base, cu16cnt, val);
  495. set_roi_cu16_base_cfg(dst_base, zindex, val);
  496. set_roi_cu16_qp_cfg(dst_qp, zindex, cu16_cfg);
  497. /*
  498. * if all cu16 adjust c64 and cu32 must adjust
  499. * or we will force split to cu 16
  500. */
  501. if (adjust_cnt == 16 && cu16cnt == 15) {
  502. // cu64
  503. set_roi_cu64_base_cfg(dst_base, val);
  504. set_roi_cu64_qp_cfg(dst_qp, cu16_cfg);
  505. // cu32
  506. for (i = 0; i < 4; i++) {
  507. set_roi_cu32_base_cfg(dst_base, i, val);
  508. set_roi_cu32_qp_cfg(dst_qp, i, cu16_cfg);
  509. }
  510. for (i = 0; i < 64; i ++) {
  511. set_roi_cu8_base_cfg(dst_base, i, val);
  512. set_roi_qp_cfg(dst_qp, i, cu16_cfg);
  513. }
  514. } else if (cu16cnt == 15 && adjust_cnt > 0) {
  515. val.force_split = 1;
  516. set_roi_force_split(dst_base, 84, val.force_split);
  517. for (i = 0; i < 4; i++) {
  518. set_roi_force_split(dst_base, 80 + i, val.force_split);
  519. }
  520. for (i = 0; i < 16; i++) {
  521. set_roi_force_split(dst_base, 64 + i, val.force_split);
  522. }
  523. }
  524. }
  525. }
  526. #if 0
  527. if (j < 3 && (k < 3 )) {
  528. mpp_log("j %d, k %d need_update = %d", j, k, need_update);
  529. RK_U16 *qp_val = (RK_U16 *)dst_qp;
  530. for (i = 0; i < CU_BASE_CFG_BYTE / 4; i++) {
  531. mpp_log("cfg[%d] = %08x", i, dst_base[i]);
  532. }
  533. for (i = 0; i < CU_QP_CFG_BYTE / 2; i++) {
  534. mpp_log("qp[%d] = %04x", i, qp_val[i]);
  535. }
  536. }
  537. #endif
  538. dst_base += CU_BASE_CFG_BYTE / 4;
  539. dst_qp += CU_QP_CFG_BYTE;
  540. }
  541. }
  542. return MPP_OK;
  543. }
  544. MPP_RET mpp_enc_roi_init(MppEncRoiCtx *ctx, RK_U32 w, RK_U32 h, MppCodingType type, RK_S32 count)
  545. {
  546. RockchipSocType soc_type = mpp_get_soc_type();
  547. RoiType roi_type = ROI_TYPE_AUTO;
  548. MppEncRoiImpl *impl = NULL;
  549. MPP_RET ret = MPP_NOK;
  550. switch (soc_type) {
  551. case ROCKCHIP_SOC_RV1109 :
  552. case ROCKCHIP_SOC_RV1126 :
  553. case ROCKCHIP_SOC_RK3566 :
  554. case ROCKCHIP_SOC_RK3568 : {
  555. roi_type = ROI_TYPE_1;
  556. } break;
  557. case ROCKCHIP_SOC_RK3588 : {
  558. roi_type = ROI_TYPE_2;
  559. } break;
  560. default : {
  561. roi_type = ROI_TYPE_LEGACY;
  562. mpp_log("soc %s run with legacy roi config\n", mpp_get_soc_name());
  563. } break;
  564. }
  565. mpp_env_get_u32("roi_type", (RK_U32 *)&roi_type, roi_type);
  566. impl = mpp_calloc(MppEncRoiImpl, 1);
  567. if (!impl) {
  568. mpp_log("can't create roi context\n");
  569. goto done;
  570. }
  571. impl->w = w;
  572. impl->h = h;
  573. impl->type = type;
  574. impl->roi_type = roi_type;
  575. impl->max_count = count;
  576. impl->regions = mpp_calloc(RoiRegionCfg, count);
  577. switch (roi_type) {
  578. case ROI_TYPE_1 : {
  579. RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
  580. RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
  581. RK_U32 ctu_w = MPP_ALIGN(impl->w, 64) / 64;
  582. RK_U32 ctu_h = MPP_ALIGN(impl->w, 64) / 64;
  583. RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
  584. RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
  585. mpp_log("set to vepu54x roi generation\n");
  586. impl->base_cfg_size = stride_h * stride_v * sizeof(Vepu541RoiCfg);
  587. mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
  588. mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
  589. if (!impl->roi_cfg.base_cfg_buf) {
  590. goto done;
  591. }
  592. impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
  593. /* create tmp buffer for hevc */
  594. if (type == MPP_VIDEO_CodingHEVC) {
  595. impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
  596. impl->cu_map = mpp_calloc(RK_U8, ctu_w * ctu_h);
  597. impl->cu_size = ctu_w * ctu_h;
  598. if (!impl->tmp || !impl->cu_map)
  599. goto done;
  600. } else {
  601. impl->cu_map = mpp_calloc(RK_U8, mb_w * mb_h);
  602. impl->cu_size = mb_w * mb_h;
  603. if (!impl->cu_map)
  604. goto done;
  605. }
  606. ret = MPP_OK;
  607. } break;
  608. case ROI_TYPE_2 : {
  609. if (type == MPP_VIDEO_CodingHEVC) {
  610. RK_U32 ctu_w = MPP_ALIGN(w, 64) / 64;
  611. RK_U32 ctu_h = MPP_ALIGN(h, 64) / 64;
  612. impl->base_cfg_size = ctu_w * ctu_h * 64;
  613. impl->qp_cfg_size = ctu_w * ctu_h * 256;
  614. impl->amv_cfg_size = ctu_w * ctu_h * 512;
  615. impl->mv_cfg_size = ctu_w * ctu_h * 4;
  616. impl->cu_map = mpp_calloc(RK_U8, ctu_w * ctu_h);
  617. impl->cu_size = ctu_w * ctu_h;
  618. } else {
  619. RK_U32 mb_w = MPP_ALIGN(w, 64) / 16;
  620. RK_U32 mb_h = MPP_ALIGN(h, 64) / 16;
  621. impl->base_cfg_size = mb_w * mb_h * 8;
  622. impl->qp_cfg_size = mb_w * mb_h * 2;
  623. impl->amv_cfg_size = mb_w * mb_h / 4;
  624. impl->mv_cfg_size = mb_w * mb_h * 96 / 4;
  625. impl->cu_map = mpp_calloc(RK_U8, mb_w * mb_h);
  626. impl->cu_size = mb_w * mb_h;
  627. }
  628. mpp_log("set to vepu58x roi generation\n");
  629. impl->roi_cfg.roi_qp_en = 1;
  630. mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
  631. mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
  632. if (!impl->roi_cfg.base_cfg_buf) {
  633. goto done;
  634. }
  635. impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
  636. mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.qp_cfg_buf, impl->qp_cfg_size);
  637. if (!impl->roi_cfg.qp_cfg_buf) {
  638. goto done;
  639. }
  640. impl->dst_qp = mpp_buffer_get_ptr(impl->roi_cfg.qp_cfg_buf);
  641. mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.amv_cfg_buf, impl->amv_cfg_size);
  642. if (!impl->roi_cfg.amv_cfg_buf) {
  643. goto done;
  644. }
  645. impl->dst_amv = mpp_buffer_get_ptr(impl->roi_cfg.amv_cfg_buf);
  646. mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.mv_cfg_buf, impl->mv_cfg_size);
  647. if (!impl->roi_cfg.mv_cfg_buf) {
  648. goto done;
  649. }
  650. impl->dst_mv = mpp_buffer_get_ptr(impl->roi_cfg.mv_cfg_buf);
  651. {
  652. // create tmp buffer for vepu54x H.264 config first
  653. RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
  654. RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
  655. RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
  656. RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
  657. impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
  658. if (!impl->tmp)
  659. goto done;
  660. }
  661. ret = MPP_OK;
  662. } break;
  663. case ROI_TYPE_LEGACY : {
  664. impl->legacy_roi_region = mpp_calloc(MppEncROIRegion, count);
  665. mpp_assert(impl->legacy_roi_region);
  666. impl->legacy_roi_cfg.regions = impl->legacy_roi_region;
  667. ret = MPP_OK;
  668. } break;
  669. default : {
  670. } break;
  671. }
  672. done:
  673. if (ret) {
  674. if (impl) {
  675. mpp_enc_roi_deinit(impl);
  676. impl = NULL;
  677. }
  678. }
  679. *ctx = impl;
  680. return ret;
  681. }
  682. MPP_RET mpp_enc_roi_deinit(MppEncRoiCtx ctx)
  683. {
  684. MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
  685. if (!impl)
  686. return MPP_OK;
  687. if (impl->roi_cfg.base_cfg_buf) {
  688. mpp_buffer_put(impl->roi_cfg.base_cfg_buf);
  689. impl->roi_cfg.base_cfg_buf = NULL;
  690. }
  691. if (impl->roi_cfg.qp_cfg_buf) {
  692. mpp_buffer_put(impl->roi_cfg.qp_cfg_buf);
  693. impl->roi_cfg.qp_cfg_buf = NULL;
  694. }
  695. if (impl->roi_cfg.amv_cfg_buf) {
  696. mpp_buffer_put(impl->roi_cfg.amv_cfg_buf);
  697. impl->roi_cfg.amv_cfg_buf = NULL;
  698. }
  699. if (impl->roi_cfg.mv_cfg_buf) {
  700. mpp_buffer_put(impl->roi_cfg.mv_cfg_buf);
  701. impl->roi_cfg.mv_cfg_buf = NULL;
  702. }
  703. if (impl->roi_grp) {
  704. mpp_buffer_group_put(impl->roi_grp);
  705. impl->roi_grp = NULL;
  706. }
  707. MPP_FREE(impl->cu_map);
  708. MPP_FREE(impl->legacy_roi_region);
  709. MPP_FREE(impl->regions);
  710. MPP_FREE(impl->tmp);
  711. MPP_FREE(impl);
  712. return MPP_OK;
  713. }
  714. MPP_RET mpp_enc_roi_add_region(MppEncRoiCtx ctx, RoiRegionCfg *region)
  715. {
  716. MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
  717. if (impl->count >= impl->max_count) {
  718. mpp_err("can not add more region with max %d\n", impl->max_count);
  719. return MPP_NOK;
  720. }
  721. memcpy(impl->regions + impl->count, region, sizeof(*impl->regions));
  722. impl->count++;
  723. return MPP_OK;
  724. }
  725. MPP_RET mpp_enc_roi_setup_meta(MppEncRoiCtx ctx, MppMeta meta)
  726. {
  727. MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
  728. switch (impl->roi_type) {
  729. case ROI_TYPE_1 : {
  730. switch (impl->type) {
  731. case MPP_VIDEO_CodingAVC : {
  732. gen_vepu54x_roi(impl, impl->dst_base);
  733. } break;
  734. case MPP_VIDEO_CodingHEVC : {
  735. gen_vepu54x_roi(impl, impl->tmp);
  736. vepu54x_h265_set_roi(impl->dst_base, impl->tmp, impl->w, impl->h);
  737. } break;
  738. default : {
  739. } break;
  740. }
  741. mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
  742. mpp_buffer_sync_ro_end(impl->roi_cfg.base_cfg_buf);
  743. } break;
  744. case ROI_TYPE_2 : {
  745. gen_vepu54x_roi(impl, impl->tmp);
  746. switch (impl->type) {
  747. case MPP_VIDEO_CodingAVC : {
  748. gen_vepu580_roi_h264(impl);
  749. } break;
  750. case MPP_VIDEO_CodingHEVC : {
  751. gen_vepu580_roi_h265(impl);
  752. } break;
  753. default : {
  754. } break;
  755. }
  756. mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
  757. mpp_buffer_sync_ro_end(impl->roi_cfg.base_cfg_buf);
  758. mpp_buffer_sync_ro_end(impl->roi_cfg.qp_cfg_buf);
  759. } break;
  760. case ROI_TYPE_LEGACY : {
  761. MppEncROIRegion *region = impl->legacy_roi_region;
  762. MppEncROICfg *roi_cfg = &impl->legacy_roi_cfg;
  763. RoiRegionCfg *regions = impl->regions;
  764. RK_S32 i;
  765. for (i = 0; i < impl->count; i++) {
  766. region[i].x = regions[i].x;
  767. region[i].y = regions[i].y;
  768. region[i].w = regions[i].w;
  769. region[i].h = regions[i].h;
  770. region[i].intra = regions[i].force_intra;
  771. region[i].abs_qp_en = regions[i].qp_mode;
  772. region[i].quality = regions[i].qp_val;
  773. region[i].area_map_en = 1;
  774. region[i].qp_area_idx = 0;
  775. }
  776. roi_cfg->number = impl->count;
  777. roi_cfg->regions = region;
  778. mpp_meta_set_ptr(meta, KEY_ROI_DATA, (void*)roi_cfg);
  779. } break;
  780. default : {
  781. } break;
  782. }
  783. impl->count = 0;
  784. return MPP_OK;
  785. }