|
- /**************************************************************************************
- * Copyright (c) 2018-2020 ["Peking University Shenzhen Graduate School",
- * "Peng Cheng Laboratory", and "Guangdong Bohua UHD Innovation Corporation"]
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes the software uAVS3d developed by
- * Peking University Shenzhen Graduate School, Peng Cheng Laboratory
- * and Guangdong Bohua UHD Innovation Corporation.
- * 4. Neither the name of the organizations (Peking University Shenzhen Graduate School,
- * Peng Cheng Laboratory and Guangdong Bohua UHD Innovation Corporation) nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * For more information, contact us at rgwang@pkusz.edu.cn.
- **************************************************************************************/
-
- #include <math.h>
-
- #include "define.h"
- #include "analyze.h"
- #include "com_util.h"
-
- #include "../version.h"
-
- static core_t *core_alloc(com_info_t *info)
- {
- core_t *core;
- int i, j;
- core = (core_t *)com_malloc(sizeof(core_t));
- com_assert_rv(core, NULL);
- com_mset_x64a(core, 0, sizeof(core_t));
-
- for (i = 0; i < MAX_CU_DEPTH; i++) {
- for (j = 0; j < MAX_CU_DEPTH; j++) {
- enc_create_cu_data(&core->cu_data_best[i][j], i, j);
- enc_create_cu_data(&core->cu_data_temp[i][j], i, j);
- }
- }
-
- inter_search_init(&core->pinter, info, 1);
-
- int l_size = sizeof(pel) * ((MAX_CU_SIZE + SAO_SHIFT_PIX_NUM + 2) * (MAX_CU_SIZE + SAO_SHIFT_PIX_NUM + 2) + info->pic_width + ALIGN_MASK);
- int c_size = sizeof(pel) * ((MAX_CU_SIZE / 2 + SAO_SHIFT_PIX_NUM + 2) * (MAX_CU_SIZE / 2 + SAO_SHIFT_PIX_NUM + 2) + info->pic_width / 2 + ALIGN_MASK);
-
- core->sao_src_buf[0] = com_malloc(l_size);
- com_assert_rv(core->sao_src_buf[0], NULL);
- core->sao_src_buf[1] = com_malloc(c_size);
- com_assert_rv(core->sao_src_buf[1], NULL);
- core->sao_src_buf[2] = com_malloc(c_size);
- com_assert_rv(core->sao_src_buf[2], NULL);
-
- return core;
- }
-
- static void core_free(core_t *core)
- {
- int i, j;
- for (i = 0; i < MAX_CU_DEPTH; i++) {
- for (j = 0; j < MAX_CU_DEPTH; j++) {
- enc_delete_cu_data(&core->cu_data_best[i][j]);
- enc_delete_cu_data(&core->cu_data_temp[i][j]);
- }
- }
-
- com_mfree(core->sao_src_buf[0]);
- com_mfree(core->sao_src_buf[1]);
- com_mfree(core->sao_src_buf[2]);
-
- com_mfree(core);
- }
-
- static enc_pic_t *pic_enc_alloc(com_info_t *info)
- {
- enc_pic_t *ep;
- u8 *buf;
- int ret;
- int dqp_bufsize = (info->pic_width / UNIT_SIZE) * (info->pic_height / UNIT_SIZE);
- int linebuf_intra_size = ALIGN_MASK * 5 + sizeof(pel) * ((info->pic_width + MAX_CU_SIZE) * 2 + 3);
-
- int total_mem_size =
- ALIGN_MASK * 1 + sizeof(enc_pic_t) +
- ALIGN_MASK * 1 + sizeof( enc_cu_t) * info->f_lcu + // map_cu_data
- ALIGN_MASK * 1 + sizeof( s8) * info->f_lcu * info->cus_in_lcu * MAX_CU_DEPTH * NUM_BLOCK_SHAPE + // map.map_split
- ALIGN_MASK * 1 + sizeof( s8) * info->f_lcu + // map.map_qp
- ALIGN_MASK * 1 + sizeof(com_scu_t) * info->f_scu + // map.map_scu
- ALIGN_MASK * 1 + sizeof( u8) * info->f_scu + // map.map_edge
- ALIGN_MASK * 1 + sizeof( s8) * info->f_scu + // map.map_cud
- ALIGN_MASK * 1 + sizeof( s8) * info->f_scu + // map.map_ipm
- ALIGN_MASK * 1 + sizeof( s8) * info->f_scu + // map.map_patch
- ALIGN_MASK * 1 + sizeof( u32) * info->f_scu + // map.map_pos
-
- ALIGN_MASK * 1 + sizeof( float) * dqp_bufsize + // map.map_dqp
- ALIGN_MASK * 1 + (linebuf_intra_size + sizeof(pel *) * 3) * info->pic_height_in_lcu + // linebuf_intra
- ALIGN_MASK * 3 + sizeof(pel) * ((info->pic_width + MAX_CU_SIZE) * 2 + 3) + // linebuf_sao
- ALIGN_MASK * 1 + sizeof( u8) * info->f_lcu + // alf_var_map
- ALIGN_MASK * 1 + sizeof( enc_alf_corr_t) * info->f_lcu * N_C + // Enc_ALF.m_alfCorr
- ALIGN_MASK * 1 + sizeof( BOOL) * info->f_lcu * N_C + // Enc_ALF.m_AlfLCUEnabled
- ALIGN_MASK * 1 + sizeof(com_sao_param_t) * info->f_lcu * N_C + // sao_blk_params
- ALIGN_MASK * 1 + sizeof(enc_lcu_row_t) * info->pic_height_in_lcu + // array_row
- ALIGN_MASK * 2 + MAX_BS_BUF * 2 + // bs_buf + bs_buf_demulate
- ALIGN_MASK * 3 + sizeof(s16) * (info->pic_height + 2 * 8) * (info->pic_width + 2 * 8) * 3 + // ip_tmp_buf
- ALIGN_MASK;
-
- buf = com_malloc(total_mem_size);
-
- GIVE_BUFFER(ep, buf, sizeof(enc_pic_t));
- memcpy(&ep->info, info, sizeof(com_info_t));
-
- GIVE_BUFFER(ep->map_cu_data , buf, sizeof(enc_cu_t ) * info->f_lcu);
- GIVE_BUFFER(ep->map.map_split , buf, sizeof(s8 ) * info->f_lcu * info->cus_in_lcu * MAX_CU_DEPTH * NUM_BLOCK_SHAPE);
- GIVE_BUFFER(ep->map.map_qp , buf, sizeof(s8 ) * info->f_lcu);
- GIVE_BUFFER(ep->map.map_dqp , buf, sizeof(float ) * dqp_bufsize);
- GIVE_BUFFER(ep->map.map_scu , buf, sizeof(com_scu_t) * info->f_scu); ep->map.map_scu += info->i_scu + 1;
- GIVE_BUFFER(ep->map.map_edge , buf, sizeof(u8 ) * info->f_scu); ep->map.map_edge += info->i_scu + 1;
- GIVE_BUFFER(ep->map.map_ipm , buf, sizeof(s8 ) * info->f_scu); ep->map.map_ipm += info->i_scu + 1;
- GIVE_BUFFER(ep->map.map_cud , buf, sizeof(s8 ) * info->f_scu); ep->map.map_cud += info->i_scu + 1;
- GIVE_BUFFER(ep->map.map_patch , buf, sizeof(s8 ) * info->f_scu); ep->map.map_patch += info->i_scu + 1;
- GIVE_BUFFER(ep->map.map_pos , buf, sizeof(u32 ) * info->f_scu); ep->map.map_pos += info->i_scu + 1;
- GIVE_BUFFER(ep->linebuf_intra , buf, sizeof(pel *) * 3 * info->pic_height_in_lcu);
-
- for (int i = 0; i < info->pic_height_in_lcu; i++) {
- GIVE_BUFFER(ep->linebuf_intra[i][0], buf, sizeof(pel) *(info->pic_width + MAX_CU_SIZE + 1));
- ep->linebuf_intra[i][0] += 1;
- GIVE_BUFFER(ep->linebuf_intra[i][1], buf, sizeof(pel) *(info->pic_width / 2 + MAX_CU_SIZE / 2 + 1));
- ep->linebuf_intra[i][1] += 1;
- GIVE_BUFFER(ep->linebuf_intra[i][2], buf, sizeof(pel) *(info->pic_width / 2 + MAX_CU_SIZE / 2 + 1));
- ep->linebuf_intra[i][2] += 1;
- }
- GIVE_BUFFER(ep->linebuf_sao[0], buf, sizeof(pel) *(info->pic_width + MAX_CU_SIZE + 1));
- ep->linebuf_sao[0] += 1;
- GIVE_BUFFER(ep->linebuf_sao[1], buf, sizeof(pel) *(info->pic_width / 2 + MAX_CU_SIZE / 2 + 1));
- ep->linebuf_sao[1] += 1;
- GIVE_BUFFER(ep->linebuf_sao[2], buf, sizeof(pel) *(info->pic_width / 2 + MAX_CU_SIZE / 2 + 1));
- ep->linebuf_sao[2] += 1;
-
- GIVE_BUFFER(ep->alf_var_map, buf, sizeof(s8) * info->f_lcu);
- com_alf_buf_init(info, ep->alf_var_map);
- ep->Enc_ALF.m_coeffNoFilter[ALF_MAX_NUM_COEF - 1] = (1 << ALF_NUM_BIT_SHIFT);
-
- GIVE_BUFFER(ep->Enc_ALF.m_alfCorr, buf, sizeof( enc_alf_corr_t) * info->f_lcu * N_C);
- GIVE_BUFFER(ep->Enc_ALF.m_AlfLCUEnabled, buf, sizeof( BOOL) * info->f_lcu * N_C);
- GIVE_BUFFER(ep->sao_blk_params, buf, sizeof(com_sao_param_t) * info->f_lcu * N_C);
- GIVE_BUFFER(ep->array_row, buf, sizeof(enc_lcu_row_t ) * info->pic_height_in_lcu);
- GIVE_BUFFER(ep->bs_buf_demulate, buf, MAX_BS_BUF);
-
- GIVE_BUFFER(ep->ip_tmp_buf[0], buf, sizeof(s16) * (info->pic_width + 2 * 8) * (info->pic_height + 2 * 8));
- GIVE_BUFFER(ep->ip_tmp_buf[1], buf, sizeof(s16) * (info->pic_width + 2 * 8) * (info->pic_height + 2 * 8));
- GIVE_BUFFER(ep->ip_tmp_buf[2], buf, sizeof(s16) * (info->pic_width + 2 * 8) * (info->pic_height + 2 * 8));
-
- for (int i = 0; i < info->pic_height_in_lcu; i++) {
- uavs3e_sem_init(&ep->array_row[i].sem, 0, 0);
- }
-
- uavs3e_threadpool_init(&ep->wpp_threads_pool, info->wpp_threads, info->pic_height_in_lcu, (void * (*)(void *))core_alloc, info, (void(*)(void *))core_free);
-
- for (int i = 0; i < info->f_lcu; i++) {
- enc_create_cu_data(ep->map_cu_data + i, info->log2_max_cuwh - MIN_CU_LOG2, info->log2_max_cuwh - MIN_CU_LOG2);
- }
-
- ep->pic_alf_Rec = com_pic_create(info->pic_width, info->pic_height, PIC_PAD_SIZE_L, PIC_PAD_SIZE_C, &ret);
-
- ep->main_core = core_alloc(info);
-
- inter_search_init(&ep->pinter, info, 1);
-
- return ep;
- }
-
- static void pic_enc_free(enc_pic_t *ep)
- {
- uavs3e_threadpool_delete(ep->wpp_threads_pool);
-
- for (int i = 0; i < ep->info.f_lcu; i++) {
- enc_delete_cu_data(ep->map_cu_data + i);
- }
- for (int i = 0; i < ep->info.pic_height_in_lcu; i++) {
- uavs3e_sem_destroy(&ep->array_row[i].sem);
- }
- com_pic_destroy(ep->pic_alf_Rec);
- core_free(ep->main_core);
-
- com_mfree(ep);
- }
-
- static int refine_input_cfg(enc_cfg_t *param, enc_cfg_t *cfg_org)
- {
- /***************************************************************************/
- /* refine config by speed_level */
- /***************************************************************************/
- if (SPEED_LEVEL(1, cfg_org->speed_level)) {
- cfg_org->max_bt_size = 64;
- }
- if (SPEED_LEVEL(2, cfg_org->speed_level)) {
- cfg_org->max_eqt_size = 32;
- }
- if (SPEED_LEVEL(3, cfg_org->speed_level)) {
- cfg_org->max_dt_size = 16;
- }
- /***************************************************************************/
- cfg_org->ipf_flag = 0;
- com_mcpy(param, cfg_org, sizeof(enc_cfg_t));
-
- if (param->bit_depth_internal == 0) {
- param->bit_depth_internal = param->bit_depth_input;
- }
- if (param->bit_depth_internal == 8) {
- param->qp = COM_CLIP3(0, MAX_QUANT_BASE, param->qp);
- } else {
- param->qp = COM_CLIP3(-16, MAX_QUANT_BASE, param->qp);
- }
- param->pic_width = (param->horizontal_size + PIC_ALIGN_SIZE - 1) / PIC_ALIGN_SIZE * PIC_ALIGN_SIZE;
- param->pic_height = (param->vertical_size + PIC_ALIGN_SIZE - 1) / PIC_ALIGN_SIZE * PIC_ALIGN_SIZE;
-
- if (param->horizontal_size % PIC_ALIGN_SIZE != 0) {
- printf("Note: picture width in encoding process is padded to %d (input value %d)\n", param->pic_width, param->horizontal_size);
- }
- if (param->vertical_size % PIC_ALIGN_SIZE != 0) {
- printf("Note: picture height in encoding process is padded to %d (input value %d)\n", param->pic_height, param->vertical_size);
- }
- if (param->bit_depth_input > param->bit_depth_internal) {
- printf("Warning: Data precision may lose because input bit depth is higher than internal one !\n");
- }
- param->wpp_threads = COM_CLIP3(1, (param->pic_height + param->ctu_size - 1) / param->ctu_size, param->wpp_threads);
- param->frm_threads = COM_MAX(param->frm_threads, 1);
-
- if (param->i_period == 1) {
- param->max_b_frames = 0;
- param->close_gop = 1;
- }
- if (param->max_b_frames == 0) {
- param->adaptive_gop = 0;
- }
- param->lookahead = COM_MAX(param->lookahead, param->max_b_frames + 1);
-
- /* check input parameters */
- com_assert_rv (param->pic_width > 0 && param->pic_height > 0, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv((param->pic_width & (MIN_CU_SIZE - 1)) == 0, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv((param->pic_height & (MIN_CU_SIZE - 1)) == 0, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->qp >= ( - (8 *(param->bit_depth_internal - 8))), COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->qp <= MAX_QUANT_BASE, COM_ERR_INVALID_ARGUMENT); // this assertion is align with the constraint for input QP
- com_assert_rv(param->i_period >= 0, COM_ERR_INVALID_ARGUMENT);
-
- com_assert_rv(param->chroma_format == 1, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->patch_width == 0 && param->patch_height == 0, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->bit_depth_input == 8 || param->bit_depth_input == 10, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->bit_depth_internal == 8 || param->bit_depth_internal == 10, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->emvr_enable == 0 || (param->amvr_enable && param->num_of_hmvp), COM_ERR_INVALID_ARGUMENT);
-
- com_assert_rv(param->ctu_size == 32 || param->ctu_size == 64 || param->ctu_size == 128, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->min_cu_size == 4, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->max_part_ratio == 8, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->max_split_times == 6, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->min_qt_size == 4 || param->min_qt_size == 8 || param->min_qt_size == 16 || param->min_qt_size == 32 || param->min_qt_size == 64 || param->min_qt_size == 128, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->max_bt_size == 64 || param->max_bt_size == 128, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->max_eqt_size == 8 || param->max_eqt_size == 16 || param->max_eqt_size == 32 || param->max_eqt_size == 64, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->max_dt_size == 16 || param->max_dt_size == 32 || param->max_dt_size == 64, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->min_cu_size <= param->ctu_size, COM_ERR_INVALID_ARGUMENT);
-
- com_assert_rv(com_tbl_log2[param->max_b_frames + 1] != -1, COM_ERR_INVALID_ARGUMENT);
- com_assert_rv(param->max_b_frames < MAX_SUBGOP_SIZE, COM_ERR_INVALID_ARGUMENT);
-
- #if (BIT_DEPTH == 8)
- if (param->bit_depth_internal == 10) {
- com_assert_rv(0, COM_ERR_INVALID_ARGUMENT);
- }
- #endif
- return COM_OK;
- }
-
- int load_wq_matrix(char *fn, u8 *m4x4_out, u8 *m8x8_out)
- {
- int i, m4x4[16], m8x8[64];
- sscanf(fn, "[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d]\n",
- &m4x4[ 0], &m4x4[ 1], &m4x4[ 2], &m4x4[ 3], &m4x4[ 4], &m4x4[ 5], &m4x4[ 6], &m4x4[ 7],
- &m4x4[ 8], &m4x4[ 9], &m4x4[10], &m4x4[11], &m4x4[12], &m4x4[13], &m4x4[14], &m4x4[15],
- &m8x8[ 0], &m8x8[ 1], &m8x8[ 2], &m8x8[ 3], &m8x8[ 4], &m8x8[ 5], &m8x8[ 6], &m8x8[ 7],
- &m8x8[ 8], &m8x8[ 9], &m8x8[10], &m8x8[11], &m8x8[12], &m8x8[13], &m8x8[14], &m8x8[15],
- &m8x8[16], &m8x8[17], &m8x8[18], &m8x8[19], &m8x8[20], &m8x8[21], &m8x8[22], &m8x8[23],
- &m8x8[24], &m8x8[25], &m8x8[26], &m8x8[27], &m8x8[28], &m8x8[29], &m8x8[30], &m8x8[31],
- &m8x8[32], &m8x8[33], &m8x8[34], &m8x8[35], &m8x8[36], &m8x8[37], &m8x8[38], &m8x8[39],
- &m8x8[40], &m8x8[41], &m8x8[42], &m8x8[43], &m8x8[44], &m8x8[45], &m8x8[46], &m8x8[47],
- &m8x8[48], &m8x8[49], &m8x8[50], &m8x8[51], &m8x8[52], &m8x8[53], &m8x8[54], &m8x8[55],
- &m8x8[56], &m8x8[57], &m8x8[58], &m8x8[59], &m8x8[60], &m8x8[61], &m8x8[62], &m8x8[63]);
-
- for (i = 0; i < 16; i++) {
- m4x4_out[i] = m4x4[i];
- }
- for (i = 0; i < 64; i++) {
- m8x8_out[i] = m8x8[i];
- }
-
- return COM_OK;
- }
-
- static void set_sqh(enc_ctrl_t *h, com_seqh_t *sqh)
- {
- int i;
- static const double fps_code_tab[14] = { 0, 24000.0 / 1001.0, 24.0, 25.0, 30000.0 / 1001.0, 30.0, 50.0, 60000.0 / 1001.0, 60.0, 100, 120, 200, 240, 300 };
- double fps = h->cfg.fps_num * 1.0 / h->cfg.fps_den;
- double min_diff = 100;
-
- sqh->profile_id = PROFILE_ID;
- sqh->level_id = LEVEL_ID;
- sqh->progressive_sequence = 1;
- sqh->field_coded_sequence = 0;
- sqh->sample_precision = h->cfg.bit_depth_input == 8 ? 1 : 2;
- sqh->aspect_ratio = 1;
-
- sqh->frame_rate_code = 15;
-
- for (i = 0; i < 14; i++) {
- double diff = fabs(fps - fps_code_tab[i]);
- if (diff < min_diff) {
- min_diff = diff;
- sqh->frame_rate_code = i;
- }
- }
-
- sqh->bit_rate_lower = 0;
- sqh->bit_rate_upper = 0;
- sqh->low_delay = h->cfg.max_b_frames == 0 ? 1 : 0;
- sqh->temporal_id_enable_flag = 1;
- sqh->bbv_buffer_size = (1 << 18) - 1;
- sqh->max_dpb_size = 16;
-
- sqh->rpl1_index_exist_flag = 1;
-
- if (h->cfg.max_b_frames) {
- static com_rpl_t rpl_l0[MAX_RPLS] = {
- { 3, MAX_RA_ACTIVE, { 16, 32, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 18, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 19, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 2, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 4, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 5, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 2, 6, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 8, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 9, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 10, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 2, 11, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 4, 12, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 5, 13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 4, MAX_RA_ACTIVE, { 2, 6, 14, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }}
- };
- static com_rpl_t rpl_l1[MAX_RPLS] = {
- { 2, MAX_RA_ACTIVE, { 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 4, MAX_RA_ACTIVE, { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 1, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 3, MAX_RA_ACTIVE, { 1, 2, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 3, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 13, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 1, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { 2, MAX_RA_ACTIVE, { 15, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }}
- };
- sqh->rpl1_same_as_rpl0_flag = 0;
- sqh->rpls_l0_num = MAX_RPLS;
- sqh->rpls_l1_num = MAX_RPLS;
- memcpy(sqh->rpls_l0, &rpl_l0, sizeof(rpl_l0));
- memcpy(sqh->rpls_l1, &rpl_l1, sizeof(rpl_l1));
- } else {
- static com_rpl_t rpl[4] = {
- { MAX_LD_ACTIVE, MAX_LD_ACTIVE, { 1, 5, 9, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { MAX_LD_ACTIVE, MAX_LD_ACTIVE, { 1, 2, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { MAX_LD_ACTIVE, MAX_LD_ACTIVE, { 1, 3, 7, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }},
- { MAX_LD_ACTIVE, MAX_LD_ACTIVE, { 1, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }}
- };
- sqh->rpl1_same_as_rpl0_flag = 1;
- sqh->rpls_l0_num = 4;
- sqh->rpls_l1_num = 4;
- memcpy(sqh->rpls_l0, &rpl, sizeof(rpl));
- memcpy(sqh->rpls_l1, &rpl, sizeof(rpl));
- }
-
- sqh->horizontal_size = h->cfg.horizontal_size;
- sqh->vertical_size = h->cfg.vertical_size;
- sqh->log2_max_cuwh = h->info.log2_max_cuwh;
- sqh->min_cu_size = h->cfg.min_cu_size;
- sqh->max_part_ratio = h->cfg.max_part_ratio;
- sqh->max_split_times = h->cfg.max_split_times;
- sqh->min_qt_size = h->cfg.min_qt_size;
- sqh->max_bt_size = h->cfg.max_bt_size;
- sqh->max_eqt_size = h->cfg.max_eqt_size;
- sqh->max_dt_size = h->cfg.max_dt_size;
- sqh->amvr_enable = h->cfg.amvr_enable;
- sqh->ipf_enable_flag = h->cfg.ipf_flag;
- sqh->affine_enable = h->cfg.affine_enable;
- sqh->smvd_enable = h->cfg.smvd_enable;
- sqh->num_of_hmvp = h->cfg.num_of_hmvp;
- sqh->umve_enable = h->cfg.umve_enable;
- sqh->emvr_enable = h->cfg.emvr_enable;
- sqh->tscpm_enable = h->cfg.tscpm_enable;
- sqh->dt_enable = h->cfg.dt_enable;
- sqh->wq_enable = h->cfg.wq_enable;
- sqh->seq_wq_mode = h->cfg.seq_wq_mode;
- sqh->pbt_enable = h->cfg.pbt_enable;
- sqh->sao_enable = h->cfg.sao_enable;
- sqh->alf_enable = h->cfg.alf_enable;
- sqh->ipcm_enable_flag = 0;
-
- if (sqh->wq_enable && sqh->seq_wq_mode) {
- load_wq_matrix(h->cfg.seq_wq_user, sqh->wq_4x4_matrix, sqh->wq_8x8_matrix);
- }
- if (sqh->wq_enable) {
- if (sqh->seq_wq_mode) {
- load_wq_matrix(h->cfg.seq_wq_user, sqh->wq_4x4_matrix, sqh->wq_8x8_matrix);
- } else {
- memcpy(sqh->wq_4x4_matrix, com_tbl_wq_default_matrix_4x4, sizeof(com_tbl_wq_default_matrix_4x4));
- memcpy(sqh->wq_8x8_matrix, com_tbl_wq_default_matrix_8x8, sizeof(com_tbl_wq_default_matrix_8x8));
- }
- }
-
- sqh->sectrans_enable = (u8)h->cfg.sectrans_enable;
- sqh->chroma_format = h->cfg.chroma_format;
- sqh->encoding_precision = (h->cfg.bit_depth_internal == 8) ? 1 : 2;
-
- if (sqh->low_delay == 1) {
- sqh->output_reorder_delay = 0;
- } else {
- //for random access mode, GOP 16
- sqh->output_reorder_delay = com_tbl_log2[h->cfg.max_b_frames + 1];//log2(GopSize)
- if (com_tbl_log2[h->cfg.max_b_frames + 1] == -1) {
- for (int i = h->cfg.max_b_frames + 1; i < 257; i++) {
- if (com_tbl_log2[i] != -1) {
- sqh->output_reorder_delay = com_tbl_log2[i];
- break;
- }
- }
- }
- assert(sqh->output_reorder_delay != -1);
- }
-
- sqh->colocated_patch = h->cfg.colocated_patch;
- sqh->filter_cross_patch = h->cfg.filter_cross_patch;
- sqh->patch_width = h->cfg.patch_width == 0 ? h->info.pic_width_in_lcu : h->cfg.patch_width;
- sqh->patch_height = h->cfg.patch_height == 0 ? h->info.pic_height_in_lcu : h->cfg.patch_height;
- }
-
- static void set_pic_header(enc_ctrl_t *h, com_pic_t *pic_rec)
- {
- com_pic_header_t *pichdr = &h->pichdr;
- pichdr->bbv_delay = 0xFFFFFFFF;
- pichdr->time_code_flag = 0;
- pichdr->time_code = 0;
- pichdr->low_delay = h->info.sqh.low_delay;
-
- if (pichdr->low_delay) {
- pichdr->bbv_check_time = (1 << 16) - 2;
- }
-
- pichdr->loop_filter_disable_flag = (h->cfg.use_deblock) ? 0 : 1;
-
- if (h->info.sqh.wq_enable) {
- pichdr->pic_wq_enable = 1;//default
- pichdr->pic_wq_data_idx = h->cfg.pic_wq_data_idx;
- if (pichdr->pic_wq_data_idx == 0) {
- memcpy(pichdr->wq_4x4_matrix, h->info.sqh.wq_4x4_matrix, sizeof(pichdr->wq_4x4_matrix));
- memcpy(pichdr->wq_8x8_matrix, h->info.sqh.wq_8x8_matrix, sizeof(pichdr->wq_8x8_matrix));
- } else if (pichdr->pic_wq_data_idx == 1) {
- pichdr->wq_param = h->cfg.wq_param;
- pichdr->wq_model = h->cfg.wq_model;
-
- if (pichdr->wq_param == 0) {
- memcpy(pichdr->wq_param_vector, com_tbl_wq_default_param[1], sizeof(pichdr->wq_param_vector));
- } else if (pichdr->wq_param == 1) {
- sscanf(h->cfg.wq_param_undetailed, "[%d,%d,%d,%d,%d,%d]",
- &pichdr->wq_param_vector[0],
- &pichdr->wq_param_vector[1],
- &pichdr->wq_param_vector[2],
- &pichdr->wq_param_vector[3],
- &pichdr->wq_param_vector[4],
- &pichdr->wq_param_vector[5]);
- } else {
- sscanf(h->cfg.wq_param_detailed, "[%d,%d,%d,%d,%d,%d]",
- &pichdr->wq_param_vector[0],
- &pichdr->wq_param_vector[1],
- &pichdr->wq_param_vector[2],
- &pichdr->wq_param_vector[3],
- &pichdr->wq_param_vector[4],
- &pichdr->wq_param_vector[5]);
- }
- set_pic_wq_matrix_by_param(pichdr->wq_param_vector, pichdr->wq_model, pichdr->wq_4x4_matrix, pichdr->wq_8x8_matrix);
- } else {
- load_wq_matrix(h->cfg.pic_wq_user, pichdr->wq_4x4_matrix, pichdr->wq_8x8_matrix);
- }
- } else {
- pichdr->pic_wq_enable = 0;
- init_pic_wq_matrix(pichdr->wq_4x4_matrix, pichdr->wq_8x8_matrix);
- }
-
- pichdr->progressive_frame = 1;
- pichdr->picture_structure = 1;
- pichdr->top_field_first = 0;
- pichdr->repeat_first_field = 0;
- pichdr->top_field_picture_flag = 0;
- pichdr->fixed_picture_qp_flag = !h->cfg.adaptive_dqp;
- pichdr->random_access_decodable_flag = 1;
- pichdr->loop_filter_parameter_flag = 0;
- pichdr->alpha_c_offset = 0;
- pichdr->beta_offset = 0;
- pichdr->tool_alf_on = h->info.sqh.alf_enable;
- pichdr->affine_subblk_size_idx = 0; // 0->4X4, 1->8X8
- pichdr->picture_output_delay = (int)(pichdr->poc - h->pichdr.dtr + h->info.sqh.output_reorder_delay);
-
- if ((pichdr->dtr % DOI_CYCLE_LENGTH) < h->prev_dtr) {
- for (int i = 0; i < h->rpm.max_pb_size; i++) {
- com_pic_t *pic = h->rpm.pic[i];
- if (pic != NULL) {
- pic->dtr -= DOI_CYCLE_LENGTH;
- assert(pic->dtr >= (-256));
- }
- }
- }
-
- h->top_pic[0] = h->top_pic[1] = NULL;
-
- if (pichdr->poc == 0) {
- pichdr->ref_pic_list_sps_flag[0] = 1;
- pichdr->ref_pic_list_sps_flag[1] = 1;
- pichdr->rpl_l0_idx = 0;
- pichdr->rpl_l0_idx = 0;
- pichdr->rpl_l0.active = 0;
- pichdr->rpl_l1.active = 0;
- h->rpm.ptr_l_ip = 0;
- h->rpm.ptr_l_l_ip = 0;
- h->rpm.ptr_l_i = 0;
- } else {
- int is_ld = h->info.sqh.low_delay;
- int is_top = pic_rec->layer_id < FRM_DEPTH_2 && !is_ld;
-
- com_refm_remove_ref_pic(&h->rpm, pichdr, pic_rec, h->cfg.close_gop, is_ld);
- com_refm_build_ref_buf (&h->rpm);
-
- if (pichdr->slice_type == SLICE_I) {
- pichdr->rpl_l0.active = 0;
- pichdr->rpl_l1.active = 0;
- } else if (is_ld) {
- pichdr->rpl_l0.active = MAX_LD_ACTIVE;
- pichdr->rpl_l1.active = MAX_LD_ACTIVE;
- } else {
- pichdr->rpl_l0.active = MAX_RA_ACTIVE;
- pichdr->rpl_l1.active = MAX_RA_ACTIVE;
- }
-
- for (int i = 0; i < h->rpm.cur_num_ref_pics; i++) {
- com_pic_t *ref = h->rpm.pic[i];
- if (ref && ref->b_ref && ref->layer_id <= FRM_DEPTH_1 && (h->top_pic[0] == NULL || h->top_pic[0]->ptr < ref->ptr)) {
- h->top_pic[0] = ref;
- }
- }
- com_refm_create_rpl(&h->info, &h->rpm, pichdr, h->refp, h->top_pic, is_top);
- com_refm_pick_seqhdr_idx(&h->info.sqh, pichdr);
-
- for (int i = 0; i < 2; i++) {
- if (h->top_pic[i]) {
- com_img_addref(h->top_pic[i]->img);
- }
- }
- }
- com_refm_insert_rec_pic(&h->rpm, pic_rec, h->refp);
- }
-
- static int lbac_enc_tree(core_t *core, lbac_t *lbac, bs_t *bs, int x0, int y0, int cup, int cu_width, int cu_height, int cud
- , const int parent_split, int qt_depth, int bet_depth, u8 cons_pred_mode, u8 tree_status)
- {
- int ret;
- com_info_t *info = core->info;
- s8 split_mode;
- int lcu_pos = core->lcu_y * info->pic_width_in_lcu + core->lcu_x;
- enc_cu_t *cu_data = &core->map_cu_data[lcu_pos];
- com_get_split_mode(&split_mode, cud, cup, cu_width, cu_height, info->max_cuwh, cu_data->split_mode);
- u8 tree_status_child = TREE_LC;
- u8 cons_pred_mode_child;
-
- if (split_mode != NO_SPLIT) {
- lbac_enc_split_mode(lbac, bs, core, split_mode, cud, cup, cu_width, cu_height, info->max_cuwh, parent_split, qt_depth, bet_depth, x0, y0);
- tree_status_child = (tree_status == TREE_LC && com_tree_split(cu_width, cu_height, split_mode, core->pichdr->slice_type)) ? TREE_L : tree_status;
- if (cons_pred_mode == NO_MODE_CONS && is_use_cons(cu_width, cu_height, split_mode, core->pichdr->slice_type)) {
- cons_pred_mode_child = com_get_cons_pred_mode(cud, cup, cu_width, cu_height, info->max_cuwh, cu_data->split_mode);
- lbac_enc_cons_pred_mode(lbac, bs, cons_pred_mode_child);
- } else {
- cons_pred_mode_child = cons_pred_mode;
- }
- com_split_struct_t split_struct;
- com_split_get_part_structure(split_mode, x0, y0, cu_width, cu_height, cup, cud, info->log2_lcuwh_in_scu, &split_struct);
- for (int part_num = 0; part_num < split_struct.part_count; ++part_num) {
- int cur_part_num = part_num;
- int sub_cuw = split_struct.width[cur_part_num];
- int sub_cuh = split_struct.height[cur_part_num];
- int x_pos = split_struct.x_pos[cur_part_num];
- int y_pos = split_struct.y_pos[cur_part_num];
-
- if (x_pos < info->pic_width && y_pos < info->pic_height) {
- ret = lbac_enc_tree(core, lbac, bs, x_pos, y_pos, split_struct.cup[cur_part_num], sub_cuw, sub_cuh, split_struct.cud
- , split_mode, INC_QT_DEPTH(qt_depth, split_mode), INC_BET_DEPTH(bet_depth, split_mode), cons_pred_mode_child, tree_status_child);
- com_assert_g(!ret, ERR);
- }
- }
- if (tree_status_child == TREE_L && tree_status == TREE_LC) {
- com_assert(x0 + cu_width <= info->pic_width && y0 + cu_height <= info->pic_height);
- core->tree_status = TREE_C;
- core->cons_pred_mode = NO_MODE_CONS;
- ret = lbac_enc_unit_chroma(lbac, bs, core, cu_data, x0, y0, cup, cu_width, cu_height);
- core->tree_status = TREE_LC;
- }
- } else {
- com_assert(x0 + cu_width <= info->pic_width && y0 + cu_height <= info->pic_height);
- // map_cud
- com_map_t* map = core->map;
- int cup_in_pic = ((u32)PEL2SCU(y0) * info->i_scu) + PEL2SCU(x0);
- com_assert(map->map_cud[cup_in_pic] == qt_depth);
- lbac_enc_split_mode(lbac, bs, core, split_mode, cud, cup, cu_width, cu_height, info->max_cuwh, parent_split, qt_depth, bet_depth, x0, y0);
- core->tree_status = tree_status;
- core->cons_pred_mode = cons_pred_mode;
-
- ret = lbac_enc_unit(lbac, bs, core, cu_data, x0, y0, cup, cu_width, cu_height);
- com_assert_g(!ret, ERR);
- }
- return COM_OK;
- ERR:
- return ret;
- }
-
-
- int uavs3e_get_img(void *id, com_img_t **img)
- {
- enc_ctrl_t *h = (enc_ctrl_t *)id;
-
- for (int i = 0; i < h->ilist_size; i++) {
- if (h->ilist_imgs[i] == NULL) {
- *img = com_img_create(h->cfg.pic_width, h->cfg.pic_height, NULL, 3);
- com_assert_rv(*img != NULL, COM_ERR_OUT_OF_MEMORY);
- h->ilist_imgs[i] = *img;
- return COM_OK;
- } else if (com_img_getref(h->ilist_imgs[i]) == 1) {
- *img = h->ilist_imgs[i];
- return COM_OK;
- }
- }
- return COM_ERR_UNEXPECTED;
- }
-
- int enc_pic_finish(enc_ctrl_t *h, pic_thd_param_t *pic_thd, enc_stat_t *stat)
- {
- int i, j;
-
- com_pic_t *pic_org = &pic_thd->pic_org;
- com_pic_t *pic_rec = pic_thd->pic_rec;
- com_img_t *imgb_o = pic_org->img;
- com_img_t *imgb_c = pic_rec->img;
-
- stat->type = pic_thd->pichdr.slice_type;
- stat->qp = (float)pic_rec->picture_qp_real;
- stat->poc = pic_thd->ptr;
- stat->rec_img = imgb_c;
- stat->org_img = imgb_o;
- stat->pts = imgb_c->pts = imgb_o->pts;
- stat->dts = imgb_c->dts = imgb_o->dts;
- stat->buf = pic_thd->bs_buf;
- stat->bytes = pic_thd->total_bytes;
- stat->user_bytes = pic_thd->user_bytes;
-
- com_img_release(imgb_c);
-
- for (i = 0; i < REFP_NUM; i++) {
- com_pic_t *toppic = pic_thd->top_pic[i];
-
- if (toppic) {
- com_img_release(toppic->img);
- if (!toppic->b_ref &&toppic->subpel && 1 == com_img_getref(toppic->img)) {
- toppic->subpel->b_used = 0;
- }
- }
- stat->refpic_num[i] = pic_thd->num_refp[i];
-
- for (j = 0; j < stat->refpic_num[i]; j++) {
- com_pic_t *refpic = pic_thd->refp[j][i].pic;
- stat->refpic[i][j] = refpic->ptr;
- com_img_release(refpic->img);
-
- if (!refpic->b_ref && refpic->subpel && 1 == com_img_getref(refpic->img)) {
- refpic->subpel->b_used = 0;
- }
- }
- }
-
- if (imgb_o) {
- com_img_release(imgb_o);
- }
-
- return COM_OK;
- }
-
- void *enc_lcu_row(core_t *core, enc_lcu_row_t *row)
- {
- int lcu_y = row->lcu_y;
- enc_pic_param_t *pic_ctx = row->pic_info;
- uavs3e_sem_t *sem_up = row->sem_up;
- uavs3e_sem_t *sem_curr = row->sem_curr;
- lbac_t *lbac = &row->lbac_row;
- lbac_t *lbac_row_next = row->lbac_row_next;
-
- int last_lcu_qp = pic_ctx->pathdr->slice_qp;
- com_info_t *info = pic_ctx->info;
- com_pic_header_t *pichdr = pic_ctx->pichdr;
- u8 *map_qp = pic_ctx->map->map_qp + lcu_y * info->pic_width_in_lcu;
-
- row->total_qp = 0;
- core->cnt_hmvp_cands = 0;
- core->lcu_y = lcu_y;
- core->lcu_pix_y = lcu_y << info->log2_max_cuwh;
-
- core->param = pic_ctx->param;
- core->pichdr = pic_ctx->pichdr;
- core->pathdr = pic_ctx->pathdr;
- core->info = pic_ctx->info;
- core->map = pic_ctx->map;
- core->map_cu_data = pic_ctx->map_cu_data;
- core->sao_blk_params = pic_ctx->sao_blk_params;
- core->pic_org = pic_ctx->pic_org;
- core->pic_rec = pic_ctx->pic_rec;
- core->refp = pic_ctx->refp;
- core->ptr = pic_ctx->ptr;
- core->num_refp = pic_ctx->num_refp;
- core->slice_type = pichdr->slice_type;
- core->pinter.ptr = core->ptr;
-
- memcpy(core->linebuf_sao, pic_ctx->linebuf_sao, sizeof(pel *) * 3);
- memcpy(core->linebuf_intra[0], pic_ctx->linebuf_intra[core->lcu_y], sizeof(pel *) * 3);
-
- if (core->lcu_y) {
- memcpy(core->linebuf_intra[1], pic_ctx->linebuf_intra[core->lcu_y - 1], sizeof(pel *) * 3);
- }
-
- if (pichdr->pic_wq_enable) {
- core->wq[0] = pichdr->wq_4x4_matrix;
- core->wq[1] = pichdr->wq_8x8_matrix;
- } else {
- core->wq[0] = core->wq[1] = NULL;
- }
-
- com_mset_x64a(core->motion_cands, 0, sizeof(com_motion_t)*ALLOWED_HMVP_NUM);
-
- for (core->lcu_x = 0; core->lcu_x < info->pic_width_in_lcu; core->lcu_x++) {
- com_info_t *info = core->info;
- int lcu_qp;
- int adj_qp_cb, adj_qp_cr;
-
- if (core->lcu_x < info->pic_width_in_lcu - 1) {
- safe_sem_wait(sem_up);
- }
-
- core->lcu_pix_x = core->lcu_x << info->log2_max_cuwh;
-
- if (core->pathdr->fixed_slice_qp_flag) {
- lcu_qp = core->pathdr->slice_qp;
- } else {
- if (core->param->adaptive_dqp) {
- float *dqp_map = core->map->map_dqp + (core->lcu_pix_y / UNIT_SIZE) * (info->pic_width / UNIT_SIZE) + (core->lcu_pix_x / UNIT_SIZE);
- double dqp_all = 0;
- double blk_cnt = 0;
- int lcu_w = COM_MIN(info->max_cuwh, info->pic_width - core->lcu_pix_x);
- int lcu_h = COM_MIN(info->max_cuwh, info->pic_height - core->lcu_pix_y);
-
- for (int i = 0; i < lcu_h - (UNIT_SIZE - 1); i += UNIT_SIZE) {
- for (int j = 0; j < lcu_w - (UNIT_SIZE - 1); j += UNIT_SIZE) {
- dqp_all += dqp_map[j / UNIT_SIZE];
- blk_cnt++;
- }
- dqp_map += info->pic_width / UNIT_SIZE;
- }
- if (blk_cnt) {
- lcu_qp = (int)(core->pathdr->slice_qp + (dqp_all / blk_cnt) + 0.5);
- lcu_qp = COM_CLIP3(0, (MAX_QUANT_BASE + info->qp_offset_bit_depth), lcu_qp);
- last_lcu_qp = lcu_qp;
- } else {
- lcu_qp = core->pathdr->slice_qp;
- }
- } else {
- com_assert(0);
- }
- }
- *map_qp++ = (u8)lcu_qp;
-
- core->lcu_qp_y = lcu_qp;
-
- adj_qp_cb = core->lcu_qp_y + pichdr->chroma_quant_param_delta_cb - info->qp_offset_bit_depth;
- adj_qp_cr = core->lcu_qp_y + pichdr->chroma_quant_param_delta_cr - info->qp_offset_bit_depth;
-
- adj_qp_cb = COM_CLIP(adj_qp_cb, -16, MAX_QUANT_BASE);
- adj_qp_cr = COM_CLIP(adj_qp_cr, -16, MAX_QUANT_BASE);
-
- if (adj_qp_cb >= 0) {
- adj_qp_cb = com_tbl_qp_chroma_ajudst[COM_MIN(MAX_QUANT_BASE, adj_qp_cb)];
- }
- if (adj_qp_cr >= 0) {
- adj_qp_cr = com_tbl_qp_chroma_ajudst[COM_MIN(MAX_QUANT_BASE, adj_qp_cr)];
- }
- core->lcu_qp_u = COM_CLIP(adj_qp_cb + info->qp_offset_bit_depth, 0, MAX_QUANT_BASE + info->qp_offset_bit_depth);
- core->lcu_qp_v = COM_CLIP(adj_qp_cr + info->qp_offset_bit_depth, 0, MAX_QUANT_BASE + info->qp_offset_bit_depth);
-
- lcu_qp -= info->qp_offset_bit_depth; // calculate lambda for 8-bit distortion
- row->total_qp += lcu_qp;
- core->lambda[0] = 1.43631 * pow(2.0, (lcu_qp - 16.0) / 4.0);
- core->dist_chroma_weight[0] = pow(2.0, (lcu_qp - adj_qp_cb) / 4.0);
- core->dist_chroma_weight[1] = pow(2.0, (lcu_qp - adj_qp_cr) / 4.0);
-
- core->lambda[1] = core->lambda[0] / core->dist_chroma_weight[0];
- core->lambda[2] = core->lambda[0] / core->dist_chroma_weight[1];
- core->sqrt_lambda[0] = sqrt(core->lambda[0]);
- core->sqrt_lambda[1] = sqrt(core->lambda[1]);
- core->sqrt_lambda[2] = sqrt(core->lambda[2]);
-
- core->satd_threshold = 1.1;
-
- if (info->rmv_satd_level_P1) {
- core->satd_threshold = 1.05;
- }
-
- /* initialize structures *****************************************/
- core->pinter.lambda_mv = (u32)floor(65536.0 * core->sqrt_lambda[0]);
- com_mset(core->history_data, 0, sizeof(enc_history_t) * MAX_CU_DEPTH * MAX_CU_DEPTH * MAX_CU_CNT_IN_LCU);
-
- /* mode decision *************************************************/
- enc_mode_analyze_lcu(core, lbac);
-
- /* entropy coding ************************************************/
- //write to bitstream
- if (info->sqh.sao_enable) {
- int lcu_pos = core->lcu_x + core->lcu_y * info->pic_width_in_lcu;
- lbac_enc_sao_param(lbac, NULL, core->pathdr, core->map, core->info, lcu_y, core->lcu_x, core->sao_blk_params[lcu_pos], core->sao_blk_params);
- }
- lbac_enc_tree(core, lbac, NULL, core->lcu_pix_x, core->lcu_pix_y, 0, info->max_cuwh, info->max_cuwh, 0, NO_SPLIT, 0, 0, NO_MODE_CONS, TREE_LC);
-
- /* end_of_picture_flag */
- lbac_enc_slice_end_flag(lbac, NULL, 0);
- printf("*");
- fflush(stdout);
-
- #define KEEP_CONST 0
-
- if (lbac_row_next) {
- if (core->param->wpp_threads > 1 || KEEP_CONST) {
- if (core->lcu_x == 1) {
- lbac_copy(lbac_row_next, lbac);
- }
- } else {
- if (core->lcu_x == info->pic_width_in_lcu - 1) {
- lbac_copy(lbac_row_next, lbac);
- }
- }
- }
- if (core->lcu_x >= 1) {
- safe_sem_post(sem_curr);
- }
- }
-
- com_pic_t *pic_rec = core->pic_rec;
-
- if (info->sqh.sao_enable) {
- safe_sem_wait(sem_up);
- com_sao_one_row(info, core->map, pic_rec, core->sao_blk_params, lcu_y, core->sao_src_buf, core->linebuf_sao);
- safe_sem_post(sem_curr);
- }
-
- return core;
- }
-
- void enc_get_pic_qp(enc_pic_t *ep, pic_thd_param_t *p)
- {
- com_pic_header_t *pichdr = &p->pichdr;
- enc_cfg_t *param = p->param;
- com_pic_t *pic_org = &p->pic_org;
- com_info_t *info = &ep->info;
- com_img_t *img_org = pic_org->img;
- com_img_t *ref_l0[4];
- com_img_t *ref_l1[4];
- int base_qp;
- double icost, icost_uv[2];
-
- for (int refi = 0; refi < p->num_refp[PRED_L0]; refi++) {
- ref_l0[refi] = p->refp[refi][PRED_L0].pic->img;
- }
- for (int refi = 0; refi < p->num_refp[PRED_L1]; refi++) {
- ref_l1[refi] = p->refp[refi][PRED_L1].pic->img;
- }
- for (int lidx = 0; lidx < 2; lidx++) {
- for (int ref = 0; ref < p->num_refp[lidx]; ref++) {
- wait_ref_available(p->refp[ref][lidx].pic, info->pic_height);
- }
- if (p->top_pic[lidx]) {
- wait_ref_available(p->top_pic[lidx], info->pic_height);
- }
- }
-
- float *dqp_map = param->adaptive_dqp ? ep->map.map_dqp : NULL;
-
- if (param->chroma_dqp) {
- pic_org->picture_satd = loka_estimate_coding_cost(&ep->pinter, img_org, ref_l0, ref_l1, p->num_refp, info->bit_depth_internal, &icost, icost_uv, dqp_map);
- } else {
- pic_org->picture_satd = loka_estimate_coding_cost(&ep->pinter, img_org, ref_l0, ref_l1, p->num_refp, info->bit_depth_internal, NULL, NULL, dqp_map);
- }
- if (param->rc_type == RC_TYPE_NULL) {
- base_qp = (int)(enc_get_hgop_qp(param->qp, pic_org->layer_id, info->sqh.low_delay) + 0.5);
- } else {
- int qp_l0 = p->top_pic[0] ? ((int)(p->top_pic[0]->picture_qp_real + 0.5) + (p->top_pic[0]->layer_id == FRM_DEPTH_0 ? 3 : 0)) : -1;
- int qp_l1 = p->top_pic[1] ? ((int)(p->top_pic[1]->picture_qp_real + 0.5) + (p->top_pic[1]->layer_id == FRM_DEPTH_0 ? 3 : 0)) : -1;
- base_qp = rc_get_qp(p->rc, pic_org, qp_l0, qp_l1);
- }
- pic_org->picture_qp = (u8)COM_CLIP3(0, (MAX_QUANT_BASE + info->qp_offset_bit_depth), base_qp + info->qp_offset_bit_depth);
-
- int qp_l = pic_org->picture_qp - info->qp_offset_bit_depth;
- int target_chroma_qp, opt_c_dqp;
-
- // delta QP of Cb
- if (p->param->chroma_dqp) {
- target_chroma_qp = com_tbl_qp_chroma_adjust_enc[COM_CLIP(qp_l + 1, 0, 63)] - (int)(icost / icost_uv[0]) + 1;
- } else {
- target_chroma_qp = com_tbl_qp_chroma_adjust_enc[COM_CLIP(qp_l + 1, 0, 63)];
- }
- target_chroma_qp = COM_MAX(0, target_chroma_qp);
- for (opt_c_dqp = -10; opt_c_dqp < 10; opt_c_dqp++) {
- if (target_chroma_qp == com_tbl_qp_chroma_ajudst[COM_CLIP(qp_l + opt_c_dqp, 0, 63)]) {
- break;
- }
- }
- opt_c_dqp = COM_CLIP(opt_c_dqp, -qp_l, 63 - qp_l);
- pichdr->chroma_quant_param_delta_cb = param->qp_offset_cb + opt_c_dqp;
- pichdr->chroma_quant_param_delta_cb = COM_CLIP(pichdr->chroma_quant_param_delta_cb, -16, 16);
-
- // delta QP of Cr
- if (p->param->chroma_dqp) {
- target_chroma_qp = com_tbl_qp_chroma_adjust_enc[COM_CLIP(qp_l + 1, 0, 63)] - (int)(icost / icost_uv[1]) + 1;
- } else {
- target_chroma_qp = com_tbl_qp_chroma_adjust_enc[COM_CLIP(qp_l + 1, 0, 63)];
- }
- target_chroma_qp = COM_MAX(0, target_chroma_qp);
- for (opt_c_dqp = -10; opt_c_dqp < 10; opt_c_dqp++) {
- if (target_chroma_qp == com_tbl_qp_chroma_ajudst[COM_CLIP(qp_l + opt_c_dqp, 0, 63)]) {
- break;
- }
- }
- opt_c_dqp = COM_CLIP(opt_c_dqp, -qp_l, 63 - qp_l);
- pichdr->chroma_quant_param_delta_cr = param->qp_offset_cr + opt_c_dqp;
- pichdr->chroma_quant_param_delta_cr = COM_CLIP(pichdr->chroma_quant_param_delta_cr, -16, 16);
-
- if (pichdr->chroma_quant_param_delta_cb == 0 && pichdr->chroma_quant_param_delta_cr == 0) {
- pichdr->chroma_quant_param_disable_flag = 1;
- } else {
- pichdr->chroma_quant_param_disable_flag = 0;
- }
- }
-
- void *enc_pic_thread(enc_pic_t *ep, pic_thd_param_t *p)
- {
- enc_pic_param_t pic_ctx;
- enc_cfg_t *param = p->param;
- com_patch_header_t pathdr;
- com_pic_header_t *pichdr = &p->pichdr;
- com_pic_t *pic_org = &p->pic_org;
- com_pic_t *pic_rec = p->pic_rec;
- com_map_t *map = &ep->map;
- com_info_t *info = &ep->info;
- com_img_t *img_org = pic_org->img;
-
- enc_get_pic_qp(ep, p);
-
- map->map_refi = pic_rec->map_refi;
- map->map_mv = pic_rec->map_mv;
-
- /* clear map */
- com_mset_x64a(map->map_refi - info->i_scu - 1, -1, sizeof(s8 ) * info->f_scu * REFP_NUM);
- com_mset_x64a(map->map_mv - info->i_scu - 1, 0, sizeof(s16 ) * info->f_scu * REFP_NUM * MV_D);
- com_mset_x64a(map->map_scu - info->i_scu - 1, 0, sizeof(com_scu_t) * info->f_scu);
- com_mset_x64a(map->map_pos - info->i_scu - 1, 0, sizeof(u32 ) * info->f_scu);
- com_mset_x64a(map->map_edge - info->i_scu - 1, 0, sizeof(u8 ) * info->f_scu);
- com_mset_x64a(map->map_patch - info->i_scu - 1, 0, sizeof(u8 ) * info->f_scu);
- // map_cud
- com_mset_x64a(map->map_cud - info->i_scu - 1, -1, sizeof(s8 ) * info->f_scu);
-
- pathdr.fixed_slice_qp_flag = pichdr->fixed_picture_qp_flag;
- pathdr.slice_qp = pic_org->picture_qp;
- pathdr.slice_sao_enable[Y_C] = pathdr.slice_sao_enable[U_C] = pathdr.slice_sao_enable[V_C] = 1;
-
- pic_ctx.param = param;
- pic_ctx.pichdr = pichdr;
- pic_ctx.pic_org = pic_org;
- pic_ctx.pic_rec = pic_rec;
- pic_ctx.refp = p->refp;
- pic_ctx.ptr = p->ptr;
- pic_ctx.num_refp = p->num_refp;
- pic_ctx.pathdr = &pathdr;
- pic_ctx.sao_blk_params = ep->sao_blk_params;
- pic_ctx.info = &ep->info;
- pic_ctx.map = &ep->map;
- pic_ctx.map_cu_data = ep->map_cu_data;
- pic_ctx.linebuf_intra = ep->linebuf_intra;
- memcpy(pic_ctx.linebuf_sao, ep->linebuf_sao, sizeof(pel*) * 3);
-
- p->total_qp = 0;
-
- lbac_t *lbac_fst_row = &ep->array_row[0].lbac_row;
- lbac_reset(lbac_fst_row);
- lbac_ctx_init(&lbac_fst_row->h);
-
- if (info->wpp_threads == 1) {
- for (int lcu_y = 0; lcu_y < info->pic_height_in_lcu; lcu_y++) {
- enc_lcu_row_t *row = &ep->array_row[lcu_y];
- row->pic_info = &pic_ctx;
- row->lcu_y = lcu_y;
- row->sem_up = NULL;
- row->sem_curr = NULL;
- row->lbac_row_next = (lcu_y == info->pic_height_in_lcu - 1) ? NULL : &ep->array_row[lcu_y + 1].lbac_row;
- enc_lcu_row(ep->main_core, row);
- p->total_qp += row->total_qp;
- }
- } else {
- if (pic_org->layer_id < 3) {
- uavs3e_threadpool_set_priority(ep->wpp_threads_pool, THREAD_PRIORITY_HIGHEST);
- } else if (pic_org->b_ref == 0) {
- uavs3e_threadpool_set_priority(ep->wpp_threads_pool, THREAD_PRIORITY_LOWEST);
- }
- for (int lcu_y = 0; lcu_y < info->pic_height_in_lcu; lcu_y++) {
- enc_lcu_row_t *row = &ep->array_row[lcu_y];
- row->pic_info = &pic_ctx;
- row->lcu_y = lcu_y;
- row->sem_up = lcu_y ? &ep->array_row[lcu_y - 1].sem : NULL;
- row->sem_curr = (lcu_y == info->pic_height_in_lcu - 1) ? NULL : &row->sem;
- row->lbac_row_next = (lcu_y == info->pic_height_in_lcu - 1) ? NULL : &ep->array_row[lcu_y + 1].lbac_row;
- uavs3e_threadpool_run(ep->wpp_threads_pool, (void*(*)(void *, void*))enc_lcu_row, row, 1);
- }
- for (int lcu_y = 0; lcu_y < info->pic_height_in_lcu; lcu_y++) {
- enc_lcu_row_t *row = &ep->array_row[lcu_y];
- uavs3e_threadpool_wait(ep->wpp_threads_pool, row);
- p->total_qp += row->total_qp;
- }
- uavs3e_threadpool_set_priority(ep->wpp_threads_pool, THREAD_PRIORITY_NORMAL);
- }
- printf("\n");
-
- if (info->sqh.alf_enable) {
- double lambda = 1.43631 * pow(2.0, (p->total_qp * 1.0 / info->f_lcu - 16.0) / 4.0);
- pichdr->m_alfPictureParam = ep->Enc_ALF.m_alfPictureParam;
- pichdr->pic_alf_on = ep->pic_alf_on;
- uavs3e_alf_frame(ep, pic_rec, pic_org, lambda);
- } else {
- pichdr->m_alfPictureParam = NULL;
- pichdr->pic_alf_on = NULL;
- }
-
- pic_rec->picture_qp_real = (p->total_qp * 1.0 / info->f_lcu);
- pic_rec->picture_qp = pic_org->picture_qp;
- pic_rec->picture_satd = pic_org->picture_satd;
- pic_rec->layer_id = pic_org->layer_id;
-
- if (pic_org->b_ref) {
- com_img_padding(pic_rec->img, 3, 0);
- com_if_luma_frame(pic_rec->subpel->imgs, ep->ip_tmp_buf, info->bit_depth_internal);
- uavs3e_pthread_mutex_lock(&pic_rec->mutex);
- pic_rec->end_line = info->pic_height;
- uavs3e_pthread_cond_broadcast(&pic_rec->cv);
- uavs3e_pthread_mutex_unlock(&pic_rec->mutex);
- }
-
- /* Bit-stream re-writing (START) */
- bs_t bs;
- bs_init(&bs, p->bs_buf, ep->bs_buf_demulate, MAX_BS_BUF);
-
- if (pichdr->slice_type == SLICE_I) {
- ec_write_sqh(&bs, &info->sqh);
- bs_flush(&bs);
- }
- ec_write_pichdr(&bs, pichdr, &info->sqh, pic_org);
- bs_flush(&bs);
-
- p->user_bytes = 0;
-
- if (param->use_pic_sign) {
- int cur_bytes = BS_GET_BYTES(&bs);
- ec_write_ext_and_usr_data(&bs, param->use_pic_sign, pic_rec, 1, 0, 0);
- bs_flush(&bs);
- p->user_bytes = BS_GET_BYTES(&bs) - cur_bytes;
- }
-
- p->total_bytes = BS_GET_BYTES(&bs);
-
- bs_init(&bs, bs.cur, bs.buftmp, ((int)(bs.end - bs.cur)) + 1);
-
- /* Encode patch header */
- ec_write_patch_hdr(&bs, &info->sqh, pichdr, &pathdr, 0);
-
- core_t *core = ep->main_core;
- core->lcu_x = 0;
- core->lcu_y = 0;
- core->lcu_pix_x = 0;
- core->lcu_pix_y = 0;
- core->param = param;
- core->pichdr = pichdr;
- core->info = info;
- core->pic_org = pic_org;
- core->pic_rec = pic_rec;
- core->refp = p->refp;
- core->ptr = p->ptr;
- core->num_refp = p->num_refp;
- core->pathdr = &pathdr;
- core->sao_blk_params = ep->sao_blk_params;
- core->map = &ep->map;
- core->map_cu_data = ep->map_cu_data;
- core->slice_type = pichdr->slice_type;
-
- for (int i = 0; i < info->f_scu; i++) {
- map->map_scu[i].coded = 0;
- }
-
- int lcu_pos = 0;
- lbac_t lbac_enc;
- lbac_t *lbac = &lbac_enc;
- lbac_reset(lbac);
- lbac_ctx_init(&lbac->h);
-
- /* Encode slice data */
- int last_lcu_qp = pathdr.slice_qp;
- int last_lcu_delta_qp = 0;
- u8 *map_qp = map->map_qp;
-
- for (core->lcu_y = 0; core->lcu_y < info->pic_height_in_lcu; core->lcu_y++) {
- core->lcu_pix_y = core->lcu_y << info->log2_max_cuwh;
-
- for (core->lcu_x = 0; core->lcu_x < info->pic_width_in_lcu; core->lcu_x++) {
- core->lcu_pix_x = core->lcu_x << info->log2_max_cuwh;
-
- if (!pathdr.fixed_slice_qp_flag) {
- int qp = *map_qp++;
- int dqp = qp - last_lcu_qp;
- lbac_enc_lcu_delta_qp(lbac, &bs, dqp, last_lcu_delta_qp);
- last_lcu_qp = qp;
- last_lcu_delta_qp = dqp;
- }
- if (info->sqh.sao_enable) {
- lbac_enc_sao_param(lbac, &bs, &pathdr, &ep->map, info, core->lcu_y, core->lcu_x, ep->sao_blk_params[lcu_pos], ep->sao_blk_params);
- }
- if (info->sqh.alf_enable) {
- for (int compIdx = Y_C; compIdx < N_C; compIdx++) {
- if (ep->pic_alf_on[compIdx]) {
- lbac_enc_alf_flag(lbac, &bs, (int)ep->Enc_ALF.m_AlfLCUEnabled[lcu_pos][compIdx]);
- }
- }
- }
- lbac_enc_tree(core, lbac, &bs, core->lcu_pix_x, core->lcu_pix_y, 0, info->max_cuwh, info->max_cuwh, 0, NO_SPLIT, 0, 0, NO_MODE_CONS, TREE_LC);
-
- /* end_of_picture_flag */
- if (++lcu_pos < info->f_lcu) {
- lbac_enc_slice_end_flag(lbac, &bs, 0);
- } else {
- lbac_enc_slice_end_flag(lbac, &bs, 1);
- lbac_finish(lbac, &bs);
- break;
- }
- }
- }
-
- bs_write1(&bs, 1);// stuffing bit
-
- while (!IS_BYTE_ALIGN(&bs)) {
- bs_write1(&bs, 0);
- }
-
- bs_demulate(&bs);
-
- /*encode patch end*/
- ec_write_patch_end(&bs);
-
- /* de-init BSW */
- bs_flush(&bs);
-
- /* set stat */
- p->total_bytes += BS_GET_BYTES(&bs);
- pic_rec->picture_bits = (p->total_bytes - p->user_bytes) * 8;
-
- return ep;
- }
-
- static void enc_push_frm(enc_ctrl_t *h, com_img_t *img, int insert_idr)
- {
- img->ptr = h->ptr++;
-
- com_img_addref(img);
-
- if (h->cfg.i_period == 1) { // AI
- add_input_node(h, img, 1, FRM_DEPTH_0, SLICE_I);
- h->lastI_ptr = img->ptr;
- return;
- }
- if (h->info.sqh.low_delay) { // LD
- if (h->lastI_ptr == -1 || insert_idr || (h->cfg.i_period && img->ptr - h->lastI_ptr == h->cfg.i_period)) {
- add_input_node(h, img, 1, FRM_DEPTH_0, SLICE_I);
- h->lastI_ptr = img->ptr;
- } else {
- static tab_s8 tbl_slice_depth_P[4] = { FRM_DEPTH_3, FRM_DEPTH_2, FRM_DEPTH_3, FRM_DEPTH_1 };
- int frm_depth = tbl_slice_depth_P[(img->ptr - h->lastI_ptr - 1) % 4];
- add_input_node(h, img, 1, frm_depth, SLICE_B);
- }
- return;
- }
-
- /*** RA ***/
- if (h->lastI_ptr == -1) { // First frame
- add_input_node(h, img, 1, FRM_DEPTH_0, SLICE_I);
- h->lastI_ptr = img->ptr;
- h->img_lastIP = img;
- if (h->cfg.scenecut_histogram) {
- calculate_histogram(&h->pinter, img, h->lastIP_histo_data, h->info.bit_depth_internal);
- h->lastIP_sc_ratio = 0;
- }
- com_img_addref(img);
- return;
- }
-
- com_img_t *last_img = h->img_rsize ? h->img_rlist[h->img_rsize - 1].img : h->img_lastIP;
- int bit_depth = h->info.bit_depth_internal;
-
- h->img_rlist[h->img_rsize].img = img;
- h->img_rlist[h->img_rsize].insert_idr = insert_idr;
- if (h->cfg.scenecut_histogram) {
- calculate_histogram(&h->pinter, img, h->img_rlist[h->img_rsize].histo_data, bit_depth);
- }
- h->img_rlist[h->img_rsize].sc_ratio = loka_get_sc_ratio(&h->pinter, img, last_img, bit_depth);
- h->img_rsize++;
-
- if (h->img_rsize < h->cfg.lookahead) {
- return;
- }
- loka_slicetype_decision(h);
- }
-
- void *uavs3e_create(enc_cfg_t *cfg, int *err)
- {
- enc_ctrl_t *h;
- com_info_t *info;
- int pic_width, pic_height;
-
- printf("Version: %s_%s, SHA-1: %s\n", VERSION_STR, VERSION_TYPE, VERSION_SHA1);
-
- h = (enc_ctrl_t *)com_malloc(sizeof(enc_ctrl_t));
- info = &h->info;
-
- refine_input_cfg(&h->cfg, cfg);
- memcpy(cfg, &h->cfg, sizeof(enc_cfg_t));
-
- pic_width = info->pic_width = h->cfg.pic_width;
- pic_height = info->pic_height = h->cfg.pic_height;
-
- info->wpp_threads = h->cfg.wpp_threads;
- info->frm_threads = h->cfg.frm_threads;
- info->max_cuwh = h->cfg.ctu_size;
- info->log2_max_cuwh = CONV_LOG2(info->max_cuwh);
- info->pic_width_in_lcu = (pic_width + info->max_cuwh - 1) >> info->log2_max_cuwh;
- info->pic_height_in_lcu = (pic_height + info->max_cuwh - 1) >> info->log2_max_cuwh;
- info->f_lcu = info->pic_width_in_lcu * info->pic_height_in_lcu;
- info->cus_in_lcu = (info->max_cuwh >> MIN_CU_LOG2) * (info->max_cuwh >> MIN_CU_LOG2);
- info->pic_width_in_scu = (pic_width + ((1 << MIN_CU_LOG2) - 1)) >> MIN_CU_LOG2;
- info->pic_height_in_scu = (pic_height + ((1 << MIN_CU_LOG2) - 1)) >> MIN_CU_LOG2;
- info->i_scu = info->pic_width_in_scu + 2;
- info->f_scu = info->i_scu * (info->pic_height_in_scu + 2);
- info->log2_lcuwh_in_scu = (u8)info->log2_max_cuwh - MIN_CU_LOG2;
- info->bit_depth_internal = h->cfg.bit_depth_internal;
- info->gop_size = h->cfg.max_b_frames + 1;
- info->max_b_frames = h->cfg.max_b_frames;
- info->bit_depth_input = h->cfg.bit_depth_input;
- info->qp_offset_bit_depth = (8 * (info->bit_depth_internal - 8));
-
- set_sqh(h, &h->info.sqh);
-
- h->prev_ptr = -1;
- h->lastI_ptr = -1;
-
- com_refm_create(&h->rpm, MAX_PB_SIZE + h->cfg.frm_threads, info->pic_width, info->pic_height);
-
- h->ilist_size = h->cfg.lookahead + h->cfg.frm_threads + 1 /* lastIP */;
- h->ilist_imgs = com_malloc(sizeof(com_img_t*) * h->ilist_size);
-
- h->img_rlist = com_malloc(sizeof(analyze_node_t) * h->cfg.lookahead);
-
- h->pic_thd_params = (pic_thd_param_t*)com_malloc(sizeof(pic_thd_param_t) * h->cfg.frm_threads);
-
- for (int i = 0; i < h->cfg.frm_threads; i++) {
- h->pic_thd_params[i].bs_buf = com_malloc(MAX_BS_BUF);
- }
-
- h->pic_thd_head = 0;
- h->pic_thd_tail = 0;
- h->pic_thd_active = 0;
-
- h->tab_mvbits_offset = inter_search_create(&h->tab_mvbits, info);
- h->info.tab_mvbits = h->tab_mvbits;
- inter_search_init(&h->pinter, info, 0);
-
- rc_init(&h->rc, &h->cfg);
-
- #if defined(ENABLE_FUNCTION_C)
- uavs3e_funs_init_c();
- #endif
-
- #if defined(ENABLE_FUNCTION_X86)
- uavs3e_funs_init_sse();
- if (uavs3e_simd_avx_level(NULL) >= 2) {
- uavs3e_funs_init_avx2();
- }
- #elif defined(ENABLE_FUNCTION_ARM64)
- uavs3e_funs_init_arm64();
- #endif
-
- com_scan_tbl_init();
- com_dct_coef_create();
- rdoq_init_err_scale(h->cfg.bit_depth_internal);
- rdoq_init_prob_2_bits();
-
- /***************************************************************************/
- /* Set Switchs for Fast algorithm */
- /***************************************************************************/
-
- if (h->cfg.i_period == 1) {
- info->ai_split_dir_decision = SPEED_LEVEL(0, h->cfg.speed_level) ? 1 : 0;
- info->ai_skip_large_cu_eqt = SPEED_LEVEL(1, h->cfg.speed_level) ? 1 : 0;
- info->ai_split_dir_decision_P1 = SPEED_LEVEL(1, h->cfg.speed_level) ? 1 : 0;
- info->ai_mpm_rdo = SPEED_LEVEL(1, h->cfg.speed_level) ? 1 : 0;
- info->ai_split_dir_decision_P2 = SPEED_LEVEL(2, h->cfg.speed_level) ? 1 : 0;
- info->ai_pred_dir_decision = SPEED_LEVEL(2, h->cfg.speed_level) ? 1 : 0;
- }
- info->adaptive_raster_range = SPEED_LEVEL(1, h->cfg.speed_level);
- info->intra_fast_rmd = SPEED_LEVEL(1, h->cfg.speed_level);
- info->depth_terminate_P1 = SPEED_LEVEL(1, h->cfg.speed_level);
- info->rmv_inter_candi_by_satd = SPEED_LEVEL(1, h->cfg.speed_level);
- info->rmv_uni_same_ref = SPEED_LEVEL(1, h->cfg.speed_level);
- info->rmv_skip_candi_by_satd = SPEED_LEVEL(1, h->cfg.speed_level);
- info->me_subpel_cost_type = SPEED_LEVEL(1, h->cfg.speed_level);
- info->depth_neb_qtd = SPEED_LEVEL(1, h->cfg.speed_level) && h->cfg.speed_level <= 1;
- info->bind_emvr_to_amvr_P1 = SPEED_LEVEL(1, h->cfg.speed_level);
- info->depth_rm_splite_by_border = SPEED_LEVEL(1, h->cfg.speed_level);
-
- info->history_skip_intra = SPEED_LEVEL(2, h->cfg.speed_level);
- info->history_skip_idx = SPEED_LEVEL(2, h->cfg.speed_level);
- info->rpl_rmv_same_ref = SPEED_LEVEL(2, h->cfg.speed_level);
- info->rmv_satd_level_P1 = SPEED_LEVEL(2, h->cfg.speed_level);
- info->depth_max_bt_32 = SPEED_LEVEL(2, h->cfg.speed_level);
-
- info->depth_terminate_P2 = SPEED_LEVEL(3, h->cfg.speed_level);
- info->bind_emvr_to_amvr_P2 = SPEED_LEVEL(3, h->cfg.speed_level);
-
- info->depth_limit_part_ratio = SPEED_LEVEL(4, h->cfg.speed_level);
-
- uavs3e_threadpool_init(&h->frm_threads_pool, h->cfg.frm_threads, h->cfg.frm_threads, (void * (*)(void *))pic_enc_alloc, &h->info, (void(*)(void *))pic_enc_free);
-
- return h;
- }
-
- void uavs3e_free(void *id)
- {
- int ret;
- enc_ctrl_t *h = (enc_ctrl_t *)id;
-
- do { // flush
- enc_stat_t stat;
- stat.ext_info = NULL;
- stat.ext_info_buf_size = 0;
- stat.insert_idr = 0;
- ret = uavs3e_enc(id, &stat, NULL);
- } while (ret == COM_OK);
-
- com_assert(h);
- com_refm_free(&h->rpm);
-
- if (h->frm_threads_pool) {
- uavs3e_threadpool_delete(h->frm_threads_pool);
- }
-
- if (h->pic_thd_params) {
- for (int i = 0; i < h->cfg.frm_threads; i++) {
- if (h->pic_thd_params[i].bs_buf) {
- com_mfree(h->pic_thd_params[i].bs_buf);
- }
- }
- com_mfree(h->pic_thd_params);
- }
- for (int i = 0; i < h->ilist_size; i++) {
- if (h->ilist_imgs[i]) {
- com_img_release(h->ilist_imgs[i]);
- }
- }
- rc_destroy(&h->rc);
- inter_search_free(h->tab_mvbits, h->tab_mvbits_offset);
-
- com_mfree(h->ilist_imgs);
- com_mfree(h->img_rlist);
-
- com_mfree(h);
- com_scan_tbl_delete();
- }
-
- static int start_one_frame(enc_ctrl_t *h)
- {
- int ret;
-
- /* initialize variables for a picture encoding */
- input_node_t node = h->node_list[0];
- com_pic_t *pic_rec = com_refm_find_free_pic(&h->rpm, node.b_ref, &ret);
-
- if (ret != COM_OK) {
- return ret;
- }
-
- for (int i = 0; i < h->node_size - 1; i++) {
- h->node_list[i] = h->node_list[i + 1];
- }
- memset(&h->node_list[h->node_size - 1], 0, sizeof(input_node_t));
- h->node_size--;
-
- com_img_t *img_org = node.img;
- com_pic_t pic_org;
-
- com_mset(&pic_org, 0, sizeof(com_pic_t));
- pic_org.y = img_org->planes[0];
- pic_org.u = img_org->planes[1];
- pic_org.v = img_org->planes[2];
- pic_org.width_luma = img_org->width [0];
- pic_org.height_luma = img_org->height[0];
- pic_org.width_chroma = img_org->width [1];
- pic_org.height_chroma = img_org->height[1];
- pic_org.stride_luma = STRIDE_IMGB2PIC(img_org->stride[0]);
- pic_org.stride_chroma = STRIDE_IMGB2PIC(img_org->stride[1]);
- pic_org.img = img_org;
- pic_org.layer_id = node.layer_id;
- pic_org.b_ref = node.b_ref;
-
- com_info_t *info = &h->info;
- com_seqh_t *sqh = &info->sqh;
- com_pic_header_t *pichdr = &h->pichdr;
-
- pichdr->slice_type = node.type;
- pichdr->poc = node.img->ptr;
- pichdr->dtr = h->dtr++;
-
- /* Set picture header */
- pic_rec->b_ref = pic_org.b_ref;
- pic_rec->layer_id = pic_org.layer_id;
- pic_rec->ptr = img_org->ptr;
- pic_rec->dtr = (s32)(h->pichdr.dtr % DOI_CYCLE_LENGTH);
- pic_rec->end_line = 0;
-
- set_pic_header(h, pic_rec);
-
- /* encode one picture */
- if (h->prev_ptr >= 0) {
- img_org->dts = img_org->pts + (pichdr->dtr - img_org->ptr) * (img_org->pts - h->prev_pts) / (img_org->ptr - h->prev_ptr);
- } else {
- img_org->dts = 0;
- }
- h->prev_dtr = pichdr->dtr % DOI_CYCLE_LENGTH;
- h->prev_ptr = img_org->ptr;
- h->prev_pts = img_org->pts;
-
- pic_thd_param_t *pic_thd_param = &h->pic_thd_params[h->pic_thd_head];
- pic_thd_param->param = &h->cfg;
- pic_thd_param->pic_rec = pic_rec;
- pic_thd_param->ptr = img_org->ptr;
- pic_thd_param->rc = &h->rc;
- pic_thd_param->top_pic[0] = h->top_pic[0];
- pic_thd_param->top_pic[1] = h->top_pic[1];
-
- memcpy(&pic_thd_param->pic_org, &pic_org, sizeof(com_pic_t));
- memcpy(&pic_thd_param->pichdr, &h->pichdr, sizeof(com_pic_header_t));
- memcpy(&pic_thd_param->num_refp, &h->rpm.num_refp, sizeof(h->rpm.num_refp));
- memcpy(&pic_thd_param->refp, &h->refp, sizeof(h->refp));
-
- uavs3e_threadpool_run(h->frm_threads_pool, (void*(*)(void *, void*))enc_pic_thread, pic_thd_param, 1);
-
- h->pic_thd_head = (h->pic_thd_head + 1) % h->cfg.frm_threads;
- h->pic_thd_active++;
-
- return ret;
- }
-
- int uavs3e_enc(void *id, enc_stat_t *stat, com_img_t *img_enc)
- {
- int ret;
- enc_ctrl_t *h = (enc_ctrl_t *)id;
-
- if (img_enc) {
- enc_push_frm(h, img_enc, stat->insert_idr);
-
- /* store input picture and return if needed */
- if (h->ptr < h->cfg.lookahead && h->cfg.max_b_frames) {
- return COM_OK_OUT_NOT_AVAILABLE;
- }
- } else { // flush
- if (h->img_rsize && !h->node_size) {
- loka_slicetype_decision(h);
- }
-
- while (h->pic_thd_active < h->cfg.frm_threads - 1 && (h->img_rsize || h->node_size)) {
- if (h->img_rsize && !h->node_size) {
- loka_slicetype_decision(h);
- }
- ret = start_one_frame(h);
- }
-
- /* check whether input pictures are remaining or not in node_input[] */
- if (!h->node_size) { // bumping
- if (h->pic_thd_active) {
- pic_thd_param_t *pic_thd_param = &h->pic_thd_params[h->pic_thd_tail];
- h->pic_thd_tail = (h->pic_thd_tail + 1) % h->cfg.frm_threads;
- uavs3e_threadpool_wait(h->frm_threads_pool, pic_thd_param);
- enc_pic_finish(h, pic_thd_param, stat);
- h->pic_thd_active--;
-
- if (h->cfg.rc_type != RC_TYPE_NULL) {
- rc_update(&h->rc, pic_thd_param->pic_rec, stat->ext_info, stat->ext_info_buf_size);
- }
- return COM_OK;
- } else {
- return COM_OK_NO_MORE_FRM;
- }
- }
- }
-
- assert(h->node_size > 0);
-
- ret = start_one_frame(h);
-
- if (h->pic_thd_active == h->cfg.frm_threads) {
- pic_thd_param_t *pic_thd_param = &h->pic_thd_params[h->pic_thd_tail];
- h->pic_thd_tail = (h->pic_thd_tail + 1) % h->cfg.frm_threads;
- uavs3e_threadpool_wait(h->frm_threads_pool, pic_thd_param);
- enc_pic_finish(h, pic_thd_param, stat);
-
- h->pic_thd_active--;
-
- if (h->cfg.rc_type != RC_TYPE_NULL) {
- rc_update(&h->rc, pic_thd_param->pic_rec, stat->ext_info, stat->ext_info_buf_size);
- }
- return COM_OK;
- } else {
- return COM_OK_OUT_NOT_AVAILABLE;
- }
- }
-
- void uavs3e_load_default_cfg(enc_cfg_t *cfg)
- {
- memset(cfg, 0, sizeof(enc_cfg_t));
-
- //#=========== Misc. ===============================
- cfg->use_pic_sign = 0;
- cfg->bit_depth_internal = 8;
- cfg->chroma_format = 1;
-
- //#========== speed/quality trade-off ==============
- cfg->speed_level = 1;
-
- //#========== parallel configuration ===============
- cfg->wpp_threads = 1;
- cfg->frm_threads = 1;
-
- //#=========== split configuration =================
- cfg->ctu_size = 128;
- cfg->min_cu_size = 4;
- cfg->max_part_ratio = 8;
- cfg->max_split_times = 6;
- cfg->min_qt_size = 8;
- cfg->max_bt_size = 128;
- cfg->max_eqt_size = 64;
- cfg->max_dt_size = 64;
-
- //#======== Coding Structure =======================
- cfg->i_period = 64;
- cfg->max_b_frames = 15;
- cfg->close_gop = 0;
- cfg->scenecut = 0;
- cfg->scenecut_histogram = 0;
- cfg->adaptive_gop = 0;
- cfg->lookahead = 40;
-
- //#========== Rate Control =========================
- cfg->rc_type = 0;
- cfg->rc_bitrate = 3000;
- cfg->rc_max_bitrate = 0;
- cfg->rc_min_qp = 0;
- cfg->rc_max_qp = 63;
- cfg->rc_crf = 34;
-
- cfg->qp = 34;
- cfg->qp_offset_cb = 0;
- cfg->qp_offset_cr = 0;
-
- //#=========== Coding Tools ========================
- cfg->amvr_enable = 1;
- cfg->affine_enable = 1;
- cfg->smvd_enable = 1;
- cfg->num_of_hmvp = 8;
- cfg->ipf_flag = 0;
- cfg->tscpm_enable = 1;
- cfg->umve_enable = 1;
- cfg->emvr_enable = 1;
- cfg->dt_enable = 1;
- cfg->sectrans_enable = 1;
- cfg->pbt_enable = 1;
- cfg->use_deblock = 1;
- cfg->sao_enable = 1;
- cfg->alf_enable = 1;
-
- //#=========== weight quant ========================
- cfg->wq_enable = 0;
- cfg->seq_wq_mode = 0;
- cfg->pic_wq_data_idx = 1;
- strcpy(cfg->seq_wq_user, "[64,64,64,68,64,64,68,72,64,68,76,80,72,76,84,96,64,64,64,64,68,68,72,76,64,64,64,68,72,76,84,92,64,64,68,72,76,80,88,100,64,68,72,80,84,92,100,112,68,72,80,84,92,104,112,128,76,80,84,92,104,116,132,152,96,100,104,116,124,140,164,188,104,108,116,128,152,172,192,216]");
- strcpy(cfg->pic_wq_user, "[64,64,64,68,64,64,68,72,64,68,76,80,72,76,84,96,64,64,64,64,68,68,72,76,64,64,64,68,72,76,84,92,64,64,68,72,76,80,88,100,64,68,72,80,84,92,100,112,68,72,80,84,92,104,112,128,76,80,84,92,104,116,132,152,96,100,104,116,124,140,164,188,104,108,116,128,152,172,192,216]");
- cfg->wq_param = 0;
- cfg->wq_model = 1;
- strcpy(cfg->wq_param_detailed, "[64,49,53,58,58,64]");
- strcpy(cfg->wq_param_undetailed, "[67,71,71,80,80,106]");
-
- //#=========== patch ===============================
- cfg->filter_cross_patch = 1;
- cfg->colocated_patch = 0;
- cfg->patch_width = 0;
- cfg->patch_height = 0;
-
- //#======= other encoder-size tools ================
- cfg->chroma_dqp = 1;
- cfg->adaptive_dqp = 0;
-
- }
|