Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  hantro_g2_hevc_dec.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Hantro VPU HEVC codec driver
 *
 * Copyright (C) 2020 Safran Passenger Innovations LLC
 */


#include "hantro_hw.h"
#include "hantro_g2_regs.h"

static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
{
 struct hantro_dev *vpu = ctx->dev;
 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
 const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
 const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
 u16 *p = (u16 *)((u8 *)ctx->hevc_dec.tile_sizes.cpu);
 unsigned int num_tile_rows = pps->num_tile_rows_minus1 + 1;
 unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
 unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
 unsigned int max_log2_ctb_size, ctb_size;
 bool tiles_enabled, uniform_spacing;
 u32 no_chroma = 0;

 tiles_enabled = !!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED);
 uniform_spacing = !!(pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING);

 hantro_reg_write(vpu, &g2_tile_e, tiles_enabled);

 max_log2_ctb_size = sps->log2_min_luma_coding_block_size_minus3 + 3 +
       sps->log2_diff_max_min_luma_coding_block_size;
 pic_width_in_ctbs = (sps->pic_width_in_luma_samples +
       (1 << max_log2_ctb_size) - 1) >> max_log2_ctb_size;
 pic_height_in_ctbs = (sps->pic_height_in_luma_samples + (1 << max_log2_ctb_size) - 1)
        >> max_log2_ctb_size;
 ctb_size = 1 << max_log2_ctb_size;

 vpu_debug(1, "Preparing tile sizes buffer for %dx%d CTBs (CTB size %d)\n",
    pic_width_in_ctbs, pic_height_in_ctbs, ctb_size);

 if (tiles_enabled) {
  unsigned int i, j, h;

  vpu_debug(1, "Tiles enabled! %dx%d\n", num_tile_cols, num_tile_rows);

  hantro_reg_write(vpu, &g2_num_tile_rows, num_tile_rows);
  hantro_reg_write(vpu, &g2_num_tile_cols, num_tile_cols);

  /* write width + height for each tile in pic */
  if (!uniform_spacing) {
   u32 tmp_w = 0, tmp_h = 0;

   for (i = 0; i < num_tile_rows; i++) {
    if (i == num_tile_rows - 1)
     h = pic_height_in_ctbs - tmp_h;
    else
     h = pps->row_height_minus1[i] + 1;
    tmp_h += h;
    if (i == 0 && h == 1 && ctb_size == 16)
     no_chroma = 1;
    for (j = 0, tmp_w = 0; j < num_tile_cols - 1; j++) {
     tmp_w += pps->column_width_minus1[j] + 1;
     *p++ = pps->column_width_minus1[j] + 1;
     *p++ = h;
     if (i == 0 && h == 1 && ctb_size == 16)
      no_chroma = 1;
    }
    /* last column */
    *p++ = pic_width_in_ctbs - tmp_w;
    *p++ = h;
   }
  } else { /* uniform spacing */
   u32 tmp, prev_h, prev_w;

   for (i = 0, prev_h = 0; i < num_tile_rows; i++) {
    tmp = (i + 1) * pic_height_in_ctbs / num_tile_rows;
    h = tmp - prev_h;
    prev_h = tmp;
    if (i == 0 && h == 1 && ctb_size == 16)
     no_chroma = 1;
    for (j = 0, prev_w = 0; j < num_tile_cols; j++) {
     tmp = (j + 1) * pic_width_in_ctbs / num_tile_cols;
     *p++ = tmp - prev_w;
     *p++ = h;
     if (j == 0 &&
         (pps->column_width_minus1[0] + 1) == 1 &&
         ctb_size == 16)
      no_chroma = 1;
     prev_w = tmp;
    }
   }
  }
 } else {
  hantro_reg_write(vpu, &g2_num_tile_rows, 1);
  hantro_reg_write(vpu, &g2_num_tile_cols, 1);

  /* There's one tile, with dimensions equal to pic size. */
  p[0] = pic_width_in_ctbs;
  p[1] = pic_height_in_ctbs;
 }

 if (no_chroma)
  vpu_debug(1, "%s: no chroma!\n", __func__);
}

static int compute_header_skip_length(struct hantro_ctx *ctx)
{
 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
 const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
 const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
 const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
 int skip = 0;

 if (pps->flags & V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT)
  /* size of pic_output_flag */
  skip++;

 if (sps->flags & V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE)
  /* size of pic_order_cnt_lsb */
  skip += 2;

 if (!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC)) {
  /* size of pic_order_cnt_lsb */
  skip += sps->log2_max_pic_order_cnt_lsb_minus4 + 4;

  /* size of short_term_ref_pic_set_sps_flag */
  skip++;

  if (decode_params->short_term_ref_pic_set_size)
   /* size of st_ref_pic_set( num_short_term_ref_pic_sets ) */
   skip += decode_params->short_term_ref_pic_set_size;
  else if (sps->num_short_term_ref_pic_sets > 1)
   skip += fls(sps->num_short_term_ref_pic_sets - 1);

  skip += decode_params->long_term_ref_pic_set_size;
 }

 return skip;
}

static void set_params(struct hantro_ctx *ctx)
{
 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
 const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
 const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
 const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
 struct hantro_dev *vpu = ctx->dev;
 u32 min_log2_cb_size, max_log2_ctb_size, min_cb_size, max_ctb_size;
 u32 pic_width_in_min_cbs, pic_height_in_min_cbs;
 u32 pic_width_aligned, pic_height_aligned;
 u32 partial_ctb_x, partial_ctb_y;

 hantro_reg_write(vpu, &g2_bit_depth_y_minus8, sps->bit_depth_luma_minus8);
 hantro_reg_write(vpu, &g2_bit_depth_c_minus8, sps->bit_depth_chroma_minus8);

 hantro_reg_write(vpu, &g2_hdr_skip_length, compute_header_skip_length(ctx));

 min_log2_cb_size = sps->log2_min_luma_coding_block_size_minus3 + 3;
 max_log2_ctb_size = min_log2_cb_size + sps->log2_diff_max_min_luma_coding_block_size;

 hantro_reg_write(vpu, &g2_min_cb_size, min_log2_cb_size);
 hantro_reg_write(vpu, &g2_max_cb_size, max_log2_ctb_size);

 min_cb_size = 1 << min_log2_cb_size;
 max_ctb_size = 1 << max_log2_ctb_size;

 pic_width_in_min_cbs = sps->pic_width_in_luma_samples / min_cb_size;
 pic_height_in_min_cbs = sps->pic_height_in_luma_samples / min_cb_size;
 pic_width_aligned = ALIGN(sps->pic_width_in_luma_samples, max_ctb_size);
 pic_height_aligned = ALIGN(sps->pic_height_in_luma_samples, max_ctb_size);

 partial_ctb_x = !!(sps->pic_width_in_luma_samples != pic_width_aligned);
 partial_ctb_y = !!(sps->pic_height_in_luma_samples != pic_height_aligned);

 hantro_reg_write(vpu, &g2_partial_ctb_x, partial_ctb_x);
 hantro_reg_write(vpu, &g2_partial_ctb_y, partial_ctb_y);

 hantro_reg_write(vpu, &g2_pic_width_in_cbs, pic_width_in_min_cbs);
 hantro_reg_write(vpu, &g2_pic_height_in_cbs, pic_height_in_min_cbs);

 hantro_reg_write(vpu, &g2_pic_width_4x4,
    (pic_width_in_min_cbs * min_cb_size) / 4);
 hantro_reg_write(vpu, &g2_pic_height_4x4,
    (pic_height_in_min_cbs * min_cb_size) / 4);

 hantro_reg_write(vpu, &hevc_max_inter_hierdepth,
    sps->max_transform_hierarchy_depth_inter);
 hantro_reg_write(vpu, &hevc_max_intra_hierdepth,
    sps->max_transform_hierarchy_depth_intra);
 hantro_reg_write(vpu, &hevc_min_trb_size,
    sps->log2_min_luma_transform_block_size_minus2 + 2);
 hantro_reg_write(vpu, &hevc_max_trb_size,
    sps->log2_min_luma_transform_block_size_minus2 + 2 +
    sps->log2_diff_max_min_luma_transform_block_size);

 hantro_reg_write(vpu, &g2_tempor_mvp_e,
    !!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED) &&
    !(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC));
 hantro_reg_write(vpu, &g2_strong_smooth_e,
    !!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED));
 hantro_reg_write(vpu, &g2_asym_pred_e,
    !!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLED));
 hantro_reg_write(vpu, &g2_sao_e,
    !!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET));
 hantro_reg_write(vpu, &g2_sign_data_hide,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED));

 if (pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED) {
  hantro_reg_write(vpu, &g2_cu_qpd_e, 1);
  hantro_reg_write(vpu, &g2_max_cu_qpd_depth, pps->diff_cu_qp_delta_depth);
 } else {
  hantro_reg_write(vpu, &g2_cu_qpd_e, 0);
  hantro_reg_write(vpu, &g2_max_cu_qpd_depth, 0);
 }

 hantro_reg_write(vpu, &g2_cb_qp_offset, pps->pps_cb_qp_offset);
 hantro_reg_write(vpu, &g2_cr_qp_offset, pps->pps_cr_qp_offset);

 hantro_reg_write(vpu, &g2_filt_offset_beta, pps->pps_beta_offset_div2);
 hantro_reg_write(vpu, &g2_filt_offset_tc, pps->pps_tc_offset_div2);
 hantro_reg_write(vpu, &g2_slice_hdr_ext_e,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT));
 hantro_reg_write(vpu, &g2_slice_hdr_ext_bits, pps->num_extra_slice_header_bits);
 hantro_reg_write(vpu, &g2_slice_chqp_present,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT));
 hantro_reg_write(vpu, &g2_weight_bipr_idc,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED));
 hantro_reg_write(vpu, &g2_transq_bypass,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED));
 hantro_reg_write(vpu, &g2_list_mod_e,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT));
 hantro_reg_write(vpu, &g2_entropy_sync_e,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED));
 hantro_reg_write(vpu, &g2_cabac_init_present,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT));
 hantro_reg_write(vpu, &g2_idr_pic_e,
    !!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC));
 hantro_reg_write(vpu, &hevc_parallel_merge,
    pps->log2_parallel_merge_level_minus2 + 2);
 hantro_reg_write(vpu, &g2_pcm_filt_d,
    !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED));
 hantro_reg_write(vpu, &g2_pcm_e,
    !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED));
 if (sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED) {
  hantro_reg_write(vpu, &g2_max_pcm_size,
     sps->log2_diff_max_min_pcm_luma_coding_block_size +
     sps->log2_min_pcm_luma_coding_block_size_minus3 + 3);
  hantro_reg_write(vpu, &g2_min_pcm_size,
     sps->log2_min_pcm_luma_coding_block_size_minus3 + 3);
  hantro_reg_write(vpu, &g2_bit_depth_pcm_y,
     sps->pcm_sample_bit_depth_luma_minus1 + 1);
  hantro_reg_write(vpu, &g2_bit_depth_pcm_c,
     sps->pcm_sample_bit_depth_chroma_minus1 + 1);
 } else {
  hantro_reg_write(vpu, &g2_max_pcm_size, 0);
  hantro_reg_write(vpu, &g2_min_pcm_size, 0);
  hantro_reg_write(vpu, &g2_bit_depth_pcm_y, 0);
  hantro_reg_write(vpu, &g2_bit_depth_pcm_c, 0);
 }

 hantro_reg_write(vpu, &g2_start_code_e, 1);
 hantro_reg_write(vpu, &g2_init_qp, pps->init_qp_minus26 + 26);
 hantro_reg_write(vpu, &g2_weight_pred_e,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED));
 hantro_reg_write(vpu, &g2_cabac_init_present,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT));
 hantro_reg_write(vpu, &g2_const_intra_e,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED));
 hantro_reg_write(vpu, &g2_transform_skip,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED));
 hantro_reg_write(vpu, &g2_out_filtering_dis,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER));
 hantro_reg_write(vpu, &g2_filt_ctrl_pres,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT));
 hantro_reg_write(vpu, &g2_dependent_slice,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED));
 hantro_reg_write(vpu, &g2_filter_override,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED));
 hantro_reg_write(vpu, &g2_refidx0_active,
    pps->num_ref_idx_l0_default_active_minus1 + 1);
 hantro_reg_write(vpu, &g2_refidx1_active,
    pps->num_ref_idx_l1_default_active_minus1 + 1);
 hantro_reg_write(vpu, &g2_apf_threshold, 8);
}

static void set_ref_pic_list(struct hantro_ctx *ctx)
{
 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
 struct hantro_dev *vpu = ctx->dev;
 const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
 u32 list0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
 u32 list1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
 static const struct hantro_reg ref_pic_regs0[] = {
  hevc_rlist_f0,
  hevc_rlist_f1,
  hevc_rlist_f2,
  hevc_rlist_f3,
  hevc_rlist_f4,
  hevc_rlist_f5,
  hevc_rlist_f6,
  hevc_rlist_f7,
  hevc_rlist_f8,
  hevc_rlist_f9,
  hevc_rlist_f10,
  hevc_rlist_f11,
  hevc_rlist_f12,
  hevc_rlist_f13,
  hevc_rlist_f14,
  hevc_rlist_f15,
 };
 static const struct hantro_reg ref_pic_regs1[] = {
  hevc_rlist_b0,
  hevc_rlist_b1,
  hevc_rlist_b2,
  hevc_rlist_b3,
  hevc_rlist_b4,
  hevc_rlist_b5,
  hevc_rlist_b6,
  hevc_rlist_b7,
  hevc_rlist_b8,
  hevc_rlist_b9,
  hevc_rlist_b10,
  hevc_rlist_b11,
  hevc_rlist_b12,
  hevc_rlist_b13,
  hevc_rlist_b14,
  hevc_rlist_b15,
 };
 unsigned int i, j;

 /* List 0 contains: short term before, short term after and long term */
 j = 0;
 for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list0); i++)
  list0[j++] = decode_params->poc_st_curr_before[i];
 for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list0); i++)
  list0[j++] = decode_params->poc_st_curr_after[i];
 for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list0); i++)
  list0[j++] = decode_params->poc_lt_curr[i];

 /* Fill the list, copying over and over */
 i = 0;
 while (j < ARRAY_SIZE(list0))
  list0[j++] = list0[i++];

 j = 0;
 for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list1); i++)
  list1[j++] = decode_params->poc_st_curr_after[i];
 for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list1); i++)
  list1[j++] = decode_params->poc_st_curr_before[i];
 for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list1); i++)
  list1[j++] = decode_params->poc_lt_curr[i];

 i = 0;
 while (j < ARRAY_SIZE(list1))
  list1[j++] = list1[i++];

 for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
  hantro_reg_write(vpu, &ref_pic_regs0[i], list0[i]);
  hantro_reg_write(vpu, &ref_pic_regs1[i], list1[i]);
 }
}

static int set_ref(struct hantro_ctx *ctx)
{
 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
 const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
 const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
 const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
 dma_addr_t luma_addr, chroma_addr, mv_addr = 0;
 dma_addr_t compress_luma_addr, compress_chroma_addr = 0;
 struct hantro_dev *vpu = ctx->dev;
 struct vb2_v4l2_buffer *vb2_dst;
 struct hantro_decoded_buffer *dst;
 size_t cr_offset = hantro_g2_chroma_offset(ctx);
 size_t mv_offset = hantro_g2_motion_vectors_offset(ctx);
 size_t compress_luma_offset = hantro_g2_luma_compress_offset(ctx);
 size_t compress_chroma_offset = hantro_g2_chroma_compress_offset(ctx);
 u32 max_ref_frames;
 u16 dpb_longterm_e;
 static const struct hantro_reg cur_poc[] = {
  hevc_cur_poc_00,
  hevc_cur_poc_01,
  hevc_cur_poc_02,
  hevc_cur_poc_03,
  hevc_cur_poc_04,
  hevc_cur_poc_05,
  hevc_cur_poc_06,
  hevc_cur_poc_07,
  hevc_cur_poc_08,
  hevc_cur_poc_09,
  hevc_cur_poc_10,
  hevc_cur_poc_11,
  hevc_cur_poc_12,
  hevc_cur_poc_13,
  hevc_cur_poc_14,
  hevc_cur_poc_15,
 };
 unsigned int i;

 max_ref_frames = decode_params->num_poc_lt_curr +
  decode_params->num_poc_st_curr_before +
  decode_params->num_poc_st_curr_after;
 /*
 * Set max_ref_frames to non-zero to avoid HW hang when decoding
 * badly marked I-frames.
 */

 max_ref_frames = max_ref_frames ? max_ref_frames : 1;
 hantro_reg_write(vpu, &g2_num_ref_frames, max_ref_frames);
 hantro_reg_write(vpu, &g2_filter_over_slices,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED));
 hantro_reg_write(vpu, &g2_filter_over_tiles,
    !!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED));

 /*
 * Write POC count diff from current pic.
 */

 for (i = 0; i < decode_params->num_active_dpb_entries && i < ARRAY_SIZE(cur_poc); i++) {
  char poc_diff = decode_params->pic_order_cnt_val - dpb[i].pic_order_cnt_val;

  hantro_reg_write(vpu, &cur_poc[i], poc_diff);
 }

 if (i < ARRAY_SIZE(cur_poc)) {
  /*
 * After the references, fill one entry pointing to itself,
 * i.e. difference is zero.
 */

  hantro_reg_write(vpu, &cur_poc[i], 0);
  i++;
 }

 /* Fill the rest with the current picture */
 for (; i < ARRAY_SIZE(cur_poc); i++)
  hantro_reg_write(vpu, &cur_poc[i], decode_params->pic_order_cnt_val);

 set_ref_pic_list(ctx);

 /* We will only keep the reference pictures that are still used */
 hantro_hevc_ref_init(ctx);

 /* Set up addresses of DPB buffers */
 dpb_longterm_e = 0;
 for (i = 0; i < decode_params->num_active_dpb_entries &&
      i < (V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1); i++) {
  luma_addr = hantro_hevc_get_ref_buf(ctx, dpb[i].pic_order_cnt_val);
  if (!luma_addr)
   return -ENOMEM;

  chroma_addr = luma_addr + cr_offset;
  mv_addr = luma_addr + mv_offset;
  compress_luma_addr = luma_addr + compress_luma_offset;
  compress_chroma_addr = luma_addr + compress_chroma_offset;

  if (dpb[i].flags & V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE)
   dpb_longterm_e |= BIT(V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1 - i);

  hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr);
  hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr);
  hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr);
  hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), compress_luma_addr);
  hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i), compress_chroma_addr);
 }

 vb2_dst = hantro_get_dst_buf(ctx);
 dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf);
 luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf);
 if (!luma_addr)
  return -ENOMEM;

 if (hantro_hevc_add_ref_buf(ctx, decode_params->pic_order_cnt_val, luma_addr))
  return -EINVAL;

 chroma_addr = luma_addr + cr_offset;
 mv_addr = luma_addr + mv_offset;
 compress_luma_addr = luma_addr + compress_luma_offset;
 compress_chroma_addr = luma_addr + compress_chroma_offset;

 hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr);
 hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr);
 hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr);
 hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), compress_luma_addr);
 hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i++), compress_chroma_addr);

 hantro_write_addr(vpu, G2_OUT_LUMA_ADDR, luma_addr);
 hantro_write_addr(vpu, G2_OUT_CHROMA_ADDR, chroma_addr);
 hantro_write_addr(vpu, G2_OUT_MV_ADDR, mv_addr);
 hantro_write_addr(vpu, G2_OUT_COMP_LUMA_ADDR, compress_luma_addr);
 hantro_write_addr(vpu, G2_OUT_COMP_CHROMA_ADDR, compress_chroma_addr);

 for (; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
  hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), 0);
  hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), 0);
  hantro_write_addr(vpu, G2_REF_MV_ADDR(i), 0);
  hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), 0);
  hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i), 0);
 }

 hantro_reg_write(vpu, &g2_refer_lterm_e, dpb_longterm_e);

 return 0;
}

static void set_buffers(struct hantro_ctx *ctx)
{
 struct vb2_v4l2_buffer *src_buf;
 struct hantro_dev *vpu = ctx->dev;
 dma_addr_t src_dma;
 u32 src_len, src_buf_len;

 src_buf = hantro_get_src_buf(ctx);

 /* Source (stream) buffer. */
 src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
 src_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
 src_buf_len = vb2_plane_size(&src_buf->vb2_buf, 0);

 hantro_write_addr(vpu, G2_STREAM_ADDR, src_dma);
 hantro_reg_write(vpu, &g2_stream_len, src_len);
 hantro_reg_write(vpu, &g2_strm_buffer_len, src_buf_len);
 hantro_reg_write(vpu, &g2_strm_start_offset, 0);
 hantro_reg_write(vpu, &g2_start_bit, 0);
 hantro_reg_write(vpu, &g2_write_mvs_e, 1);

 hantro_write_addr(vpu, G2_TILE_SIZES_ADDR, ctx->hevc_dec.tile_sizes.dma);
 hantro_write_addr(vpu, G2_TILE_FILTER_ADDR, ctx->hevc_dec.tile_filter.dma);
 hantro_write_addr(vpu, G2_TILE_SAO_ADDR, ctx->hevc_dec.tile_sao.dma);
 hantro_write_addr(vpu, G2_TILE_BSD_ADDR, ctx->hevc_dec.tile_bsd.dma);
}

static void prepare_scaling_list_buffer(struct hantro_ctx *ctx)
{
 struct hantro_dev *vpu = ctx->dev;
 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
 const struct v4l2_ctrl_hevc_scaling_matrix *sc = ctrls->scaling;
 const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
 u8 *p = ((u8 *)ctx->hevc_dec.scaling_lists.cpu);
 unsigned int scaling_list_enabled;
 unsigned int i, j, k;

 scaling_list_enabled = !!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED);
 hantro_reg_write(vpu, &g2_scaling_list_e, scaling_list_enabled);

 if (!scaling_list_enabled)
  return;

 for (i = 0; i < ARRAY_SIZE(sc->scaling_list_dc_coef_16x16); i++)
  *p++ = sc->scaling_list_dc_coef_16x16[i];

 for (i = 0; i < ARRAY_SIZE(sc->scaling_list_dc_coef_32x32); i++)
  *p++ = sc->scaling_list_dc_coef_32x32[i];

 /* 128-bit boundary */
 p += 8;

 /* write scaling lists column by column */

 for (i = 0; i < 6; i++)
  for (j = 0; j < 4; j++)
   for (k = 0; k < 4; k++)
    *p++ = sc->scaling_list_4x4[i][4 * k + j];

 for (i = 0; i < 6; i++)
  for (j = 0; j < 8; j++)
   for (k = 0; k < 8; k++)
    *p++ = sc->scaling_list_8x8[i][8 * k + j];

 for (i = 0; i < 6; i++)
  for (j = 0; j < 8; j++)
   for (k = 0; k < 8; k++)
    *p++ = sc->scaling_list_16x16[i][8 * k + j];

 for (i = 0; i < 2; i++)
  for (j = 0; j < 8; j++)
   for (k = 0; k < 8; k++)
    *p++ = sc->scaling_list_32x32[i][8 * k + j];

 hantro_write_addr(vpu, G2_HEVC_SCALING_LIST_ADDR, ctx->hevc_dec.scaling_lists.dma);
}

int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx)
{
 struct hantro_dev *vpu = ctx->dev;
 int ret;

 hantro_g2_check_idle(vpu);

 /* Prepare HEVC decoder context. */
 ret = hantro_hevc_dec_prepare_run(ctx);
 if (ret)
  return ret;

 /* Configure hardware registers. */
 set_params(ctx);

 /* set reference pictures */
 ret = set_ref(ctx);
 if (ret)
  return ret;

 set_buffers(ctx);
 prepare_tile_info_buffer(ctx);

 prepare_scaling_list_buffer(ctx);

 hantro_end_prepare_run(ctx);

 hantro_reg_write(vpu, &g2_mode, HEVC_DEC_MODE);
 hantro_reg_write(vpu, &g2_clk_gate_e, 1);

 /* Don't disable output */
 hantro_reg_write(vpu, &g2_out_dis, 0);

 hantro_reg_write(vpu, &g2_ref_compress_bypass, !ctx->hevc_dec.use_compression);

 /* Bus width and max burst */
 hantro_reg_write(vpu, &g2_buswidth, BUS_WIDTH_128);
 hantro_reg_write(vpu, &g2_max_burst, 16);

 /* Swap */
 hantro_reg_write(vpu, &g2_strm_swap, 0xf);
 hantro_reg_write(vpu, &g2_dirmv_swap, 0xf);
 hantro_reg_write(vpu, &g2_compress_swap, 0xf);

 /* Start decoding! */
 vdpu_write(vpu, G2_REG_INTERRUPT_DEC_E, G2_REG_INTERRUPT);

 return 0;
}

Messung V0.5
C=98 H=92 G=94

¤ Dauer der Verarbeitung: 0.8 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge