1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2017 Advanced Micro Devices, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "radeon_vcn_enc.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "pipe/p_video_codec.h"
31bf215546Sopenharmony_ci#include "radeon_video.h"
32bf215546Sopenharmony_ci#include "radeonsi/si_pipe.h"
33bf215546Sopenharmony_ci#include "util/u_memory.h"
34bf215546Sopenharmony_ci#include "util/u_video.h"
35bf215546Sopenharmony_ci#include "vl/vl_video_buffer.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include <stdio.h>
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cistatic const unsigned index_to_shifts[4] = {24, 16, 8, 0};
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_cistatic void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_picture_desc *picture)
42bf215546Sopenharmony_ci{
43bf215546Sopenharmony_ci   if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
44bf215546Sopenharmony_ci      struct pipe_h264_enc_picture_desc *pic = (struct pipe_h264_enc_picture_desc *)picture;
45bf215546Sopenharmony_ci      enc->enc_pic.picture_type = pic->picture_type;
46bf215546Sopenharmony_ci      enc->enc_pic.frame_num = pic->frame_num;
47bf215546Sopenharmony_ci      enc->enc_pic.pic_order_cnt = pic->pic_order_cnt;
48bf215546Sopenharmony_ci      enc->enc_pic.pic_order_cnt_type = pic->pic_order_cnt_type;
49bf215546Sopenharmony_ci      enc->enc_pic.ref_idx_l0 = pic->ref_idx_l0_list[0];
50bf215546Sopenharmony_ci      enc->enc_pic.ref_idx_l1 = pic->ref_idx_l1_list[0];
51bf215546Sopenharmony_ci      enc->enc_pic.not_referenced = pic->not_referenced;
52bf215546Sopenharmony_ci      enc->enc_pic.is_idr = (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR);
53bf215546Sopenharmony_ci      if (pic->pic_ctrl.enc_frame_cropping_flag) {
54bf215546Sopenharmony_ci         enc->enc_pic.crop_left = pic->pic_ctrl.enc_frame_crop_left_offset;
55bf215546Sopenharmony_ci         enc->enc_pic.crop_right = pic->pic_ctrl.enc_frame_crop_right_offset;
56bf215546Sopenharmony_ci         enc->enc_pic.crop_top = pic->pic_ctrl.enc_frame_crop_top_offset;
57bf215546Sopenharmony_ci         enc->enc_pic.crop_bottom = pic->pic_ctrl.enc_frame_crop_bottom_offset;
58bf215546Sopenharmony_ci      } else {
59bf215546Sopenharmony_ci         enc->enc_pic.crop_left = 0;
60bf215546Sopenharmony_ci         enc->enc_pic.crop_right = (align(enc->base.width, 16) - enc->base.width) / 2;
61bf215546Sopenharmony_ci         enc->enc_pic.crop_top = 0;
62bf215546Sopenharmony_ci         enc->enc_pic.crop_bottom = (align(enc->base.height, 16) - enc->base.height) / 2;
63bf215546Sopenharmony_ci      }
64bf215546Sopenharmony_ci      enc->enc_pic.num_temporal_layers = pic->num_temporal_layers ? pic->num_temporal_layers : 1;
65bf215546Sopenharmony_ci      enc->enc_pic.temporal_id = 0;
66bf215546Sopenharmony_ci      for (int i = 0; i < enc->enc_pic.num_temporal_layers; i++)
67bf215546Sopenharmony_ci      {
68bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].target_bit_rate = pic->rate_ctrl[i].target_bitrate;
69bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].peak_bit_rate = pic->rate_ctrl[i].peak_bitrate;
70bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].frame_rate_num = pic->rate_ctrl[i].frame_rate_num;
71bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].frame_rate_den = pic->rate_ctrl[i].frame_rate_den;
72bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].vbv_buffer_size = pic->rate_ctrl[i].vbv_buffer_size;
73bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].avg_target_bits_per_picture = pic->rate_ctrl[i].target_bits_picture;
74bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].peak_bits_per_picture_integer =
75bf215546Sopenharmony_ci            pic->rate_ctrl[i].peak_bits_picture_integer;
76bf215546Sopenharmony_ci         enc->enc_pic.rc_layer_init[i].peak_bits_per_picture_fractional =
77bf215546Sopenharmony_ci            pic->rate_ctrl[i].peak_bits_picture_fraction;
78bf215546Sopenharmony_ci      }
79bf215546Sopenharmony_ci      enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rate_ctrl[0].vbv_buf_lv;
80bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.qp = pic->quant_i_frames;
81bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.min_qp_app = 0;
82bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.max_qp_app = 51;
83bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.max_au_size = 0;
84bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.enabled_filler_data = pic->rate_ctrl[0].fill_data_enable;
85bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.skip_frame_enable = false;
86bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.enforce_hrd = pic->rate_ctrl[0].enforce_hrd;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci      switch (pic->rate_ctrl[0].rate_ctrl_method) {
89bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE:
90bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
91bf215546Sopenharmony_ci         break;
92bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP:
93bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT:
94bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_CBR;
95bf215546Sopenharmony_ci         break;
96bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP:
97bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE:
98bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method =
99bf215546Sopenharmony_ci            RENCODE_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
100bf215546Sopenharmony_ci         break;
101bf215546Sopenharmony_ci      default:
102bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
103bf215546Sopenharmony_ci      }
104bf215546Sopenharmony_ci      enc->enc_pic.spec_misc.profile_idc = u_get_h264_profile_idc(enc->base.profile);
105bf215546Sopenharmony_ci      if (enc->enc_pic.spec_misc.profile_idc >= PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN &&
106bf215546Sopenharmony_ci          enc->enc_pic.spec_misc.profile_idc != PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED)
107bf215546Sopenharmony_ci         enc->enc_pic.spec_misc.cabac_enable = pic->pic_ctrl.enc_cabac_enable;
108bf215546Sopenharmony_ci      else
109bf215546Sopenharmony_ci         enc->enc_pic.spec_misc.cabac_enable = false;
110bf215546Sopenharmony_ci      enc->enc_pic.spec_misc.cabac_init_idc = enc->enc_pic.spec_misc.cabac_enable ? pic->pic_ctrl.enc_cabac_init_idc : 0;
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   } else if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_HEVC) {
113bf215546Sopenharmony_ci      struct pipe_h265_enc_picture_desc *pic = (struct pipe_h265_enc_picture_desc *)picture;
114bf215546Sopenharmony_ci      enc->enc_pic.picture_type = pic->picture_type;
115bf215546Sopenharmony_ci      enc->enc_pic.frame_num = pic->frame_num;
116bf215546Sopenharmony_ci      enc->enc_pic.pic_order_cnt = pic->pic_order_cnt;
117bf215546Sopenharmony_ci      enc->enc_pic.pic_order_cnt_type = pic->pic_order_cnt_type;
118bf215546Sopenharmony_ci      enc->enc_pic.ref_idx_l0 = pic->ref_idx_l0;
119bf215546Sopenharmony_ci      enc->enc_pic.ref_idx_l1 = pic->ref_idx_l1;
120bf215546Sopenharmony_ci      enc->enc_pic.not_referenced = pic->not_referenced;
121bf215546Sopenharmony_ci      enc->enc_pic.is_idr = (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) ||
122bf215546Sopenharmony_ci                            (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_I);
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci      if (pic->seq.conformance_window_flag) {
125bf215546Sopenharmony_ci          enc->enc_pic.crop_left = pic->seq.conf_win_left_offset;
126bf215546Sopenharmony_ci          enc->enc_pic.crop_right = pic->seq.conf_win_right_offset;
127bf215546Sopenharmony_ci          enc->enc_pic.crop_top = pic->seq.conf_win_top_offset;
128bf215546Sopenharmony_ci          enc->enc_pic.crop_bottom = pic->seq.conf_win_bottom_offset;
129bf215546Sopenharmony_ci      } else {
130bf215546Sopenharmony_ci          enc->enc_pic.crop_left = 0;
131bf215546Sopenharmony_ci          enc->enc_pic.crop_right = (align(enc->base.width, 16) - enc->base.width) / 2;
132bf215546Sopenharmony_ci          enc->enc_pic.crop_top = 0;
133bf215546Sopenharmony_ci          enc->enc_pic.crop_bottom = (align(enc->base.height, 16) - enc->base.height) / 2;
134bf215546Sopenharmony_ci      }
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci      enc->enc_pic.general_tier_flag = pic->seq.general_tier_flag;
137bf215546Sopenharmony_ci      enc->enc_pic.general_profile_idc = pic->seq.general_profile_idc;
138bf215546Sopenharmony_ci      enc->enc_pic.general_level_idc = pic->seq.general_level_idc;
139bf215546Sopenharmony_ci      enc->enc_pic.max_poc = MAX2(16, util_next_power_of_two(pic->seq.intra_period));
140bf215546Sopenharmony_ci      enc->enc_pic.log2_max_poc = 0;
141bf215546Sopenharmony_ci      enc->enc_pic.num_temporal_layers = 1;
142bf215546Sopenharmony_ci      for (int i = enc->enc_pic.max_poc; i != 0; enc->enc_pic.log2_max_poc++)
143bf215546Sopenharmony_ci         i = (i >> 1);
144bf215546Sopenharmony_ci      enc->enc_pic.chroma_format_idc = pic->seq.chroma_format_idc;
145bf215546Sopenharmony_ci      enc->enc_pic.pic_width_in_luma_samples = pic->seq.pic_width_in_luma_samples;
146bf215546Sopenharmony_ci      enc->enc_pic.pic_height_in_luma_samples = pic->seq.pic_height_in_luma_samples;
147bf215546Sopenharmony_ci      enc->enc_pic.log2_diff_max_min_luma_coding_block_size =
148bf215546Sopenharmony_ci         pic->seq.log2_diff_max_min_luma_coding_block_size;
149bf215546Sopenharmony_ci      enc->enc_pic.log2_min_transform_block_size_minus2 =
150bf215546Sopenharmony_ci         pic->seq.log2_min_transform_block_size_minus2;
151bf215546Sopenharmony_ci      enc->enc_pic.log2_diff_max_min_transform_block_size =
152bf215546Sopenharmony_ci         pic->seq.log2_diff_max_min_transform_block_size;
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci      /* To fix incorrect hardcoded values set by player
155bf215546Sopenharmony_ci       * log2_diff_max_min_luma_coding_block_size = log2(64) - (log2_min_luma_coding_block_size_minus3 + 3)
156bf215546Sopenharmony_ci       * max_transform_hierarchy_depth_inter = log2_diff_max_min_luma_coding_block_size + 1
157bf215546Sopenharmony_ci       * max_transform_hierarchy_depth_intra = log2_diff_max_min_luma_coding_block_size + 1
158bf215546Sopenharmony_ci       */
159bf215546Sopenharmony_ci      enc->enc_pic.max_transform_hierarchy_depth_inter =
160bf215546Sopenharmony_ci         6 - (pic->seq.log2_min_luma_coding_block_size_minus3 + 3) + 1;
161bf215546Sopenharmony_ci      enc->enc_pic.max_transform_hierarchy_depth_intra =
162bf215546Sopenharmony_ci         enc->enc_pic.max_transform_hierarchy_depth_inter;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci      enc->enc_pic.log2_parallel_merge_level_minus2 = pic->pic.log2_parallel_merge_level_minus2;
165bf215546Sopenharmony_ci      enc->enc_pic.bit_depth_luma_minus8 = pic->seq.bit_depth_luma_minus8;
166bf215546Sopenharmony_ci      enc->enc_pic.bit_depth_chroma_minus8 = pic->seq.bit_depth_chroma_minus8;
167bf215546Sopenharmony_ci      enc->enc_pic.nal_unit_type = pic->pic.nal_unit_type;
168bf215546Sopenharmony_ci      enc->enc_pic.max_num_merge_cand = pic->slice.max_num_merge_cand;
169bf215546Sopenharmony_ci      enc->enc_pic.sample_adaptive_offset_enabled_flag =
170bf215546Sopenharmony_ci         pic->seq.sample_adaptive_offset_enabled_flag;
171bf215546Sopenharmony_ci      enc->enc_pic.pcm_enabled_flag = pic->seq.pcm_enabled_flag;
172bf215546Sopenharmony_ci      enc->enc_pic.sps_temporal_mvp_enabled_flag = pic->seq.sps_temporal_mvp_enabled_flag;
173bf215546Sopenharmony_ci      enc->enc_pic.hevc_deblock.loop_filter_across_slices_enabled =
174bf215546Sopenharmony_ci         pic->slice.slice_loop_filter_across_slices_enabled_flag;
175bf215546Sopenharmony_ci      enc->enc_pic.hevc_deblock.deblocking_filter_disabled =
176bf215546Sopenharmony_ci         pic->slice.slice_deblocking_filter_disabled_flag;
177bf215546Sopenharmony_ci      enc->enc_pic.hevc_deblock.beta_offset_div2 = pic->slice.slice_beta_offset_div2;
178bf215546Sopenharmony_ci      enc->enc_pic.hevc_deblock.tc_offset_div2 = pic->slice.slice_tc_offset_div2;
179bf215546Sopenharmony_ci      enc->enc_pic.hevc_deblock.cb_qp_offset = pic->slice.slice_cb_qp_offset;
180bf215546Sopenharmony_ci      enc->enc_pic.hevc_deblock.cr_qp_offset = pic->slice.slice_cr_qp_offset;
181bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.log2_min_luma_coding_block_size_minus3 =
182bf215546Sopenharmony_ci         pic->seq.log2_min_luma_coding_block_size_minus3;
183bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.amp_disabled = !pic->seq.amp_enabled_flag;
184bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.strong_intra_smoothing_enabled =
185bf215546Sopenharmony_ci         pic->seq.strong_intra_smoothing_enabled_flag;
186bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.constrained_intra_pred_flag =
187bf215546Sopenharmony_ci         pic->pic.constrained_intra_pred_flag;
188bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.cabac_init_flag = pic->slice.cabac_init_flag;
189bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.half_pel_enabled = 1;
190bf215546Sopenharmony_ci      enc->enc_pic.hevc_spec_misc.quarter_pel_enabled = 1;
191bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].target_bit_rate = pic->rc.target_bitrate;
192bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].peak_bit_rate = pic->rc.peak_bitrate;
193bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].frame_rate_num = pic->rc.frame_rate_num;
194bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].frame_rate_den = pic->rc.frame_rate_den;
195bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].vbv_buffer_size = pic->rc.vbv_buffer_size;
196bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].avg_target_bits_per_picture = pic->rc.target_bits_picture;
197bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].peak_bits_per_picture_integer = pic->rc.peak_bits_picture_integer;
198bf215546Sopenharmony_ci      enc->enc_pic.rc_layer_init[0].peak_bits_per_picture_fractional =
199bf215546Sopenharmony_ci         pic->rc.peak_bits_picture_fraction;
200bf215546Sopenharmony_ci      enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rc.vbv_buf_lv;
201bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.qp = pic->rc.quant_i_frames;
202bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.min_qp_app = 0;
203bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.max_qp_app = 51;
204bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.max_au_size = 0;
205bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.enabled_filler_data = pic->rc.fill_data_enable;
206bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.skip_frame_enable = false;
207bf215546Sopenharmony_ci      enc->enc_pic.rc_per_pic.enforce_hrd = pic->rc.enforce_hrd;
208bf215546Sopenharmony_ci      switch (pic->rc.rate_ctrl_method) {
209bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE:
210bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
211bf215546Sopenharmony_ci         break;
212bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP:
213bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT:
214bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_CBR;
215bf215546Sopenharmony_ci         break;
216bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP:
217bf215546Sopenharmony_ci      case PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE:
218bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method =
219bf215546Sopenharmony_ci            RENCODE_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
220bf215546Sopenharmony_ci         break;
221bf215546Sopenharmony_ci      default:
222bf215546Sopenharmony_ci         enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
223bf215546Sopenharmony_ci      }
224bf215546Sopenharmony_ci   }
225bf215546Sopenharmony_ci}
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_cistatic void flush(struct radeon_encoder *enc)
228bf215546Sopenharmony_ci{
229bf215546Sopenharmony_ci   enc->ws->cs_flush(&enc->cs, PIPE_FLUSH_ASYNC, NULL);
230bf215546Sopenharmony_ci}
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_cistatic void radeon_enc_flush(struct pipe_video_codec *encoder)
233bf215546Sopenharmony_ci{
234bf215546Sopenharmony_ci   struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
235bf215546Sopenharmony_ci   flush(enc);
236bf215546Sopenharmony_ci}
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_cistatic void radeon_enc_cs_flush(void *ctx, unsigned flags, struct pipe_fence_handle **fence)
239bf215546Sopenharmony_ci{
240bf215546Sopenharmony_ci   // just ignored
241bf215546Sopenharmony_ci}
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_cistatic unsigned get_cpb_num(struct radeon_encoder *enc)
244bf215546Sopenharmony_ci{
245bf215546Sopenharmony_ci   unsigned w = align(enc->base.width, 16) / 16;
246bf215546Sopenharmony_ci   unsigned h = align(enc->base.height, 16) / 16;
247bf215546Sopenharmony_ci   unsigned dpb;
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   switch (enc->base.level) {
250bf215546Sopenharmony_ci   case 10:
251bf215546Sopenharmony_ci      dpb = 396;
252bf215546Sopenharmony_ci      break;
253bf215546Sopenharmony_ci   case 11:
254bf215546Sopenharmony_ci      dpb = 900;
255bf215546Sopenharmony_ci      break;
256bf215546Sopenharmony_ci   case 12:
257bf215546Sopenharmony_ci   case 13:
258bf215546Sopenharmony_ci   case 20:
259bf215546Sopenharmony_ci      dpb = 2376;
260bf215546Sopenharmony_ci      break;
261bf215546Sopenharmony_ci   case 21:
262bf215546Sopenharmony_ci      dpb = 4752;
263bf215546Sopenharmony_ci      break;
264bf215546Sopenharmony_ci   case 22:
265bf215546Sopenharmony_ci   case 30:
266bf215546Sopenharmony_ci      dpb = 8100;
267bf215546Sopenharmony_ci      break;
268bf215546Sopenharmony_ci   case 31:
269bf215546Sopenharmony_ci      dpb = 18000;
270bf215546Sopenharmony_ci      break;
271bf215546Sopenharmony_ci   case 32:
272bf215546Sopenharmony_ci      dpb = 20480;
273bf215546Sopenharmony_ci      break;
274bf215546Sopenharmony_ci   case 40:
275bf215546Sopenharmony_ci   case 41:
276bf215546Sopenharmony_ci      dpb = 32768;
277bf215546Sopenharmony_ci      break;
278bf215546Sopenharmony_ci   case 42:
279bf215546Sopenharmony_ci      dpb = 34816;
280bf215546Sopenharmony_ci      break;
281bf215546Sopenharmony_ci   case 50:
282bf215546Sopenharmony_ci      dpb = 110400;
283bf215546Sopenharmony_ci      break;
284bf215546Sopenharmony_ci   default:
285bf215546Sopenharmony_ci   case 51:
286bf215546Sopenharmony_ci   case 52:
287bf215546Sopenharmony_ci      dpb = 184320;
288bf215546Sopenharmony_ci      break;
289bf215546Sopenharmony_ci   }
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   return MIN2(dpb / (w * h), 16);
292bf215546Sopenharmony_ci}
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_cistatic void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
295bf215546Sopenharmony_ci                                   struct pipe_video_buffer *source,
296bf215546Sopenharmony_ci                                   struct pipe_picture_desc *picture)
297bf215546Sopenharmony_ci{
298bf215546Sopenharmony_ci   struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
299bf215546Sopenharmony_ci   struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source;
300bf215546Sopenharmony_ci   bool need_rate_control = false;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
303bf215546Sopenharmony_ci      struct pipe_h264_enc_picture_desc *pic = (struct pipe_h264_enc_picture_desc *)picture;
304bf215546Sopenharmony_ci      need_rate_control =
305bf215546Sopenharmony_ci         (enc->enc_pic.rc_layer_init[0].target_bit_rate != pic->rate_ctrl[0].target_bitrate) ||
306bf215546Sopenharmony_ci         (enc->enc_pic.rc_layer_init[0].frame_rate_num != pic->rate_ctrl[0].frame_rate_num) ||
307bf215546Sopenharmony_ci         (enc->enc_pic.rc_layer_init[0].frame_rate_den != pic->rate_ctrl[0].frame_rate_den);
308bf215546Sopenharmony_ci   } else if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_HEVC) {
309bf215546Sopenharmony_ci      struct pipe_h265_enc_picture_desc *pic = (struct pipe_h265_enc_picture_desc *)picture;
310bf215546Sopenharmony_ci      need_rate_control = enc->enc_pic.rc_layer_init[0].target_bit_rate != pic->rc.target_bitrate;
311bf215546Sopenharmony_ci   }
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   radeon_vcn_enc_get_param(enc, picture);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma);
316bf215546Sopenharmony_ci   enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma);
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   enc->need_feedback = false;
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   if (!enc->stream_handle) {
321bf215546Sopenharmony_ci      struct rvid_buffer fb;
322bf215546Sopenharmony_ci      enc->stream_handle = si_vid_alloc_stream_handle();
323bf215546Sopenharmony_ci      enc->si = CALLOC_STRUCT(rvid_buffer);
324bf215546Sopenharmony_ci      si_vid_create_buffer(enc->screen, enc->si, 128 * 1024, PIPE_USAGE_STAGING);
325bf215546Sopenharmony_ci      si_vid_create_buffer(enc->screen, &fb, 4096, PIPE_USAGE_STAGING);
326bf215546Sopenharmony_ci      enc->fb = &fb;
327bf215546Sopenharmony_ci      enc->begin(enc);
328bf215546Sopenharmony_ci      flush(enc);
329bf215546Sopenharmony_ci      si_vid_destroy_buffer(&fb);
330bf215546Sopenharmony_ci   }
331bf215546Sopenharmony_ci   if (need_rate_control) {
332bf215546Sopenharmony_ci      enc->begin(enc);
333bf215546Sopenharmony_ci      flush(enc);
334bf215546Sopenharmony_ci   }
335bf215546Sopenharmony_ci}
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_cistatic void radeon_enc_encode_bitstream(struct pipe_video_codec *encoder,
338bf215546Sopenharmony_ci                                        struct pipe_video_buffer *source,
339bf215546Sopenharmony_ci                                        struct pipe_resource *destination, void **fb)
340bf215546Sopenharmony_ci{
341bf215546Sopenharmony_ci   struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
342bf215546Sopenharmony_ci   enc->get_buffer(destination, &enc->bs_handle, NULL);
343bf215546Sopenharmony_ci   enc->bs_size = destination->width0;
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   *fb = enc->fb = CALLOC_STRUCT(rvid_buffer);
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   if (!si_vid_create_buffer(enc->screen, enc->fb, 4096, PIPE_USAGE_STAGING)) {
348bf215546Sopenharmony_ci      RVID_ERR("Can't create feedback buffer.\n");
349bf215546Sopenharmony_ci      return;
350bf215546Sopenharmony_ci   }
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   enc->need_feedback = true;
353bf215546Sopenharmony_ci   enc->encode(enc);
354bf215546Sopenharmony_ci}
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_cistatic void radeon_enc_end_frame(struct pipe_video_codec *encoder, struct pipe_video_buffer *source,
357bf215546Sopenharmony_ci                                 struct pipe_picture_desc *picture)
358bf215546Sopenharmony_ci{
359bf215546Sopenharmony_ci   struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
360bf215546Sopenharmony_ci   flush(enc);
361bf215546Sopenharmony_ci}
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_cistatic void radeon_enc_destroy(struct pipe_video_codec *encoder)
364bf215546Sopenharmony_ci{
365bf215546Sopenharmony_ci   struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   if (enc->stream_handle) {
368bf215546Sopenharmony_ci      struct rvid_buffer fb;
369bf215546Sopenharmony_ci      enc->need_feedback = false;
370bf215546Sopenharmony_ci      si_vid_create_buffer(enc->screen, &fb, 512, PIPE_USAGE_STAGING);
371bf215546Sopenharmony_ci      enc->fb = &fb;
372bf215546Sopenharmony_ci      enc->destroy(enc);
373bf215546Sopenharmony_ci      flush(enc);
374bf215546Sopenharmony_ci      if (enc->si) {
375bf215546Sopenharmony_ci         si_vid_destroy_buffer(enc->si);
376bf215546Sopenharmony_ci         FREE(enc->si);
377bf215546Sopenharmony_ci         enc->si = NULL;
378bf215546Sopenharmony_ci      }
379bf215546Sopenharmony_ci      si_vid_destroy_buffer(&fb);
380bf215546Sopenharmony_ci   }
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci   si_vid_destroy_buffer(&enc->cpb);
383bf215546Sopenharmony_ci   enc->ws->cs_destroy(&enc->cs);
384bf215546Sopenharmony_ci   FREE(enc);
385bf215546Sopenharmony_ci}
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_cistatic void radeon_enc_get_feedback(struct pipe_video_codec *encoder, void *feedback,
388bf215546Sopenharmony_ci                                    unsigned *size)
389bf215546Sopenharmony_ci{
390bf215546Sopenharmony_ci   struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
391bf215546Sopenharmony_ci   struct rvid_buffer *fb = feedback;
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci   if (size) {
394bf215546Sopenharmony_ci      uint32_t *ptr = enc->ws->buffer_map(enc->ws, fb->res->buf, &enc->cs,
395bf215546Sopenharmony_ci                                          PIPE_MAP_READ_WRITE | RADEON_MAP_TEMPORARY);
396bf215546Sopenharmony_ci      if (ptr[1])
397bf215546Sopenharmony_ci         *size = ptr[6];
398bf215546Sopenharmony_ci      else
399bf215546Sopenharmony_ci         *size = 0;
400bf215546Sopenharmony_ci      enc->ws->buffer_unmap(enc->ws, fb->res->buf);
401bf215546Sopenharmony_ci   }
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   si_vid_destroy_buffer(fb);
404bf215546Sopenharmony_ci   FREE(fb);
405bf215546Sopenharmony_ci}
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_cistatic int setup_dpb(struct radeon_encoder *enc, enum pipe_format buffer_format,
408bf215546Sopenharmony_ci                     enum amd_gfx_level gfx_level)
409bf215546Sopenharmony_ci{
410bf215546Sopenharmony_ci   uint32_t aligned_width = align(enc->base.width, 16);
411bf215546Sopenharmony_ci   uint32_t aligned_height = align(enc->base.height, 16);
412bf215546Sopenharmony_ci   uint32_t rec_luma_pitch = align(aligned_width, enc->alignment);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   int luma_size = rec_luma_pitch * align(aligned_height, enc->alignment);
415bf215546Sopenharmony_ci   if (buffer_format == PIPE_FORMAT_P010)
416bf215546Sopenharmony_ci      luma_size *= 2;
417bf215546Sopenharmony_ci   int chroma_size = align(luma_size / 2, enc->alignment);
418bf215546Sopenharmony_ci   int offset = 0;
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   uint32_t num_reconstructed_pictures = enc->base.max_references + 1;
421bf215546Sopenharmony_ci   assert(num_reconstructed_pictures <= RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci   int i;
424bf215546Sopenharmony_ci   for (i = 0; i < num_reconstructed_pictures; i++) {
425bf215546Sopenharmony_ci      if (gfx_level >= GFX11) {
426bf215546Sopenharmony_ci         enc->enc_pic.ctx_buf.reconstructed_pictures_v4_0[i].luma_offset = offset;
427bf215546Sopenharmony_ci         offset += luma_size;
428bf215546Sopenharmony_ci         enc->enc_pic.ctx_buf.reconstructed_pictures_v4_0[i].chroma_offset = offset;
429bf215546Sopenharmony_ci         offset += chroma_size;
430bf215546Sopenharmony_ci      } else {
431bf215546Sopenharmony_ci         enc->enc_pic.ctx_buf.reconstructed_pictures[i].luma_offset = offset;
432bf215546Sopenharmony_ci         offset += luma_size;
433bf215546Sopenharmony_ci         enc->enc_pic.ctx_buf.reconstructed_pictures[i].chroma_offset = offset;
434bf215546Sopenharmony_ci         offset += chroma_size;
435bf215546Sopenharmony_ci      }
436bf215546Sopenharmony_ci   }
437bf215546Sopenharmony_ci   for (; i < RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES; i++) {
438bf215546Sopenharmony_ci      enc->enc_pic.ctx_buf.reconstructed_pictures[i].luma_offset = 0;
439bf215546Sopenharmony_ci      enc->enc_pic.ctx_buf.reconstructed_pictures[i].chroma_offset = 0;
440bf215546Sopenharmony_ci   }
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci   enc->enc_pic.ctx_buf.num_reconstructed_pictures = num_reconstructed_pictures;
443bf215546Sopenharmony_ci   enc->dpb_size = offset;
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci   return offset;
446bf215546Sopenharmony_ci}
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_cistruct pipe_video_codec *radeon_create_encoder(struct pipe_context *context,
449bf215546Sopenharmony_ci                                               const struct pipe_video_codec *templ,
450bf215546Sopenharmony_ci                                               struct radeon_winsys *ws,
451bf215546Sopenharmony_ci                                               radeon_enc_get_buffer get_buffer)
452bf215546Sopenharmony_ci{
453bf215546Sopenharmony_ci   struct si_screen *sscreen = (struct si_screen *)context->screen;
454bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)context;
455bf215546Sopenharmony_ci   struct radeon_encoder *enc;
456bf215546Sopenharmony_ci   struct pipe_video_buffer *tmp_buf, templat = {};
457bf215546Sopenharmony_ci   struct radeon_surf *tmp_surf;
458bf215546Sopenharmony_ci   unsigned cpb_size;
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   enc = CALLOC_STRUCT(radeon_encoder);
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   if (!enc)
463bf215546Sopenharmony_ci      return NULL;
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   enc->alignment = 256;
466bf215546Sopenharmony_ci   enc->base = *templ;
467bf215546Sopenharmony_ci   enc->base.context = context;
468bf215546Sopenharmony_ci   enc->base.destroy = radeon_enc_destroy;
469bf215546Sopenharmony_ci   enc->base.begin_frame = radeon_enc_begin_frame;
470bf215546Sopenharmony_ci   enc->base.encode_bitstream = radeon_enc_encode_bitstream;
471bf215546Sopenharmony_ci   enc->base.end_frame = radeon_enc_end_frame;
472bf215546Sopenharmony_ci   enc->base.flush = radeon_enc_flush;
473bf215546Sopenharmony_ci   enc->base.get_feedback = radeon_enc_get_feedback;
474bf215546Sopenharmony_ci   enc->get_buffer = get_buffer;
475bf215546Sopenharmony_ci   enc->bits_in_shifter = 0;
476bf215546Sopenharmony_ci   enc->screen = context->screen;
477bf215546Sopenharmony_ci   enc->ws = ws;
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   if (!ws->cs_create(&enc->cs, sctx->ctx, AMD_IP_VCN_ENC, radeon_enc_cs_flush, enc, false)) {
480bf215546Sopenharmony_ci      RVID_ERR("Can't get command submission context.\n");
481bf215546Sopenharmony_ci      goto error;
482bf215546Sopenharmony_ci   }
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   templat.buffer_format = PIPE_FORMAT_NV12;
485bf215546Sopenharmony_ci   if (enc->base.profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10)
486bf215546Sopenharmony_ci      templat.buffer_format = PIPE_FORMAT_P010;
487bf215546Sopenharmony_ci   templat.width = enc->base.width;
488bf215546Sopenharmony_ci   templat.height = enc->base.height;
489bf215546Sopenharmony_ci   templat.interlaced = false;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   if (!(tmp_buf = context->create_video_buffer(context, &templat))) {
492bf215546Sopenharmony_ci      RVID_ERR("Can't create video buffer.\n");
493bf215546Sopenharmony_ci      goto error;
494bf215546Sopenharmony_ci   }
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   enc->cpb_num = get_cpb_num(enc);
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   if (!enc->cpb_num)
499bf215546Sopenharmony_ci      goto error;
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci   get_buffer(((struct vl_video_buffer *)tmp_buf)->resources[0], NULL, &tmp_surf);
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci   cpb_size = (sscreen->info.gfx_level < GFX9)
504bf215546Sopenharmony_ci                 ? align(tmp_surf->u.legacy.level[0].nblk_x * tmp_surf->bpe, 128) *
505bf215546Sopenharmony_ci                      align(tmp_surf->u.legacy.level[0].nblk_y, 32)
506bf215546Sopenharmony_ci                 : align(tmp_surf->u.gfx9.surf_pitch * tmp_surf->bpe, 256) *
507bf215546Sopenharmony_ci                      align(tmp_surf->u.gfx9.surf_height, 32);
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   cpb_size = cpb_size * 3 / 2;
510bf215546Sopenharmony_ci   cpb_size = cpb_size * enc->cpb_num;
511bf215546Sopenharmony_ci   tmp_buf->destroy(tmp_buf);
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci   cpb_size += setup_dpb(enc, templat.buffer_format, sscreen->info.gfx_level);
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   if (!si_vid_create_buffer(enc->screen, &enc->cpb, cpb_size, PIPE_USAGE_DEFAULT)) {
516bf215546Sopenharmony_ci      RVID_ERR("Can't create CPB buffer.\n");
517bf215546Sopenharmony_ci      goto error;
518bf215546Sopenharmony_ci   }
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   if (sscreen->info.gfx_level >= GFX11)
521bf215546Sopenharmony_ci      radeon_enc_4_0_init(enc);
522bf215546Sopenharmony_ci   else if (sscreen->info.family >= CHIP_NAVI21)
523bf215546Sopenharmony_ci      radeon_enc_3_0_init(enc);
524bf215546Sopenharmony_ci   else if (sscreen->info.family >= CHIP_RENOIR)
525bf215546Sopenharmony_ci      radeon_enc_2_0_init(enc);
526bf215546Sopenharmony_ci   else
527bf215546Sopenharmony_ci      radeon_enc_1_2_init(enc);
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci   return &enc->base;
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_cierror:
532bf215546Sopenharmony_ci   enc->ws->cs_destroy(&enc->cs);
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci   si_vid_destroy_buffer(&enc->cpb);
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   FREE(enc);
537bf215546Sopenharmony_ci   return NULL;
538bf215546Sopenharmony_ci}
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_civoid radeon_enc_add_buffer(struct radeon_encoder *enc, struct pb_buffer *buf,
541bf215546Sopenharmony_ci                           unsigned usage, enum radeon_bo_domain domain, signed offset)
542bf215546Sopenharmony_ci{
543bf215546Sopenharmony_ci   enc->ws->cs_add_buffer(&enc->cs, buf, usage | RADEON_USAGE_SYNCHRONIZED, domain);
544bf215546Sopenharmony_ci   uint64_t addr;
545bf215546Sopenharmony_ci   addr = enc->ws->buffer_get_virtual_address(buf);
546bf215546Sopenharmony_ci   addr = addr + offset;
547bf215546Sopenharmony_ci   RADEON_ENC_CS(addr >> 32);
548bf215546Sopenharmony_ci   RADEON_ENC_CS(addr);
549bf215546Sopenharmony_ci}
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_civoid radeon_enc_set_emulation_prevention(struct radeon_encoder *enc, bool set)
552bf215546Sopenharmony_ci{
553bf215546Sopenharmony_ci   if (set != enc->emulation_prevention) {
554bf215546Sopenharmony_ci      enc->emulation_prevention = set;
555bf215546Sopenharmony_ci      enc->num_zeros = 0;
556bf215546Sopenharmony_ci   }
557bf215546Sopenharmony_ci}
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_civoid radeon_enc_output_one_byte(struct radeon_encoder *enc, unsigned char byte)
560bf215546Sopenharmony_ci{
561bf215546Sopenharmony_ci   if (enc->byte_index == 0)
562bf215546Sopenharmony_ci      enc->cs.current.buf[enc->cs.current.cdw] = 0;
563bf215546Sopenharmony_ci   enc->cs.current.buf[enc->cs.current.cdw] |=
564bf215546Sopenharmony_ci      ((unsigned int)(byte) << index_to_shifts[enc->byte_index]);
565bf215546Sopenharmony_ci   enc->byte_index++;
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   if (enc->byte_index >= 4) {
568bf215546Sopenharmony_ci      enc->byte_index = 0;
569bf215546Sopenharmony_ci      enc->cs.current.cdw++;
570bf215546Sopenharmony_ci   }
571bf215546Sopenharmony_ci}
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_civoid radeon_enc_emulation_prevention(struct radeon_encoder *enc, unsigned char byte)
574bf215546Sopenharmony_ci{
575bf215546Sopenharmony_ci   if (enc->emulation_prevention) {
576bf215546Sopenharmony_ci      if ((enc->num_zeros >= 2) && ((byte == 0x00) || (byte == 0x01) ||
577bf215546Sopenharmony_ci         (byte == 0x02) || (byte == 0x03))) {
578bf215546Sopenharmony_ci         radeon_enc_output_one_byte(enc, 0x03);
579bf215546Sopenharmony_ci         enc->bits_output += 8;
580bf215546Sopenharmony_ci         enc->num_zeros = 0;
581bf215546Sopenharmony_ci      }
582bf215546Sopenharmony_ci      enc->num_zeros = (byte == 0 ? (enc->num_zeros + 1) : 0);
583bf215546Sopenharmony_ci   }
584bf215546Sopenharmony_ci}
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_civoid radeon_enc_code_fixed_bits(struct radeon_encoder *enc, unsigned int value,
587bf215546Sopenharmony_ci                                unsigned int num_bits)
588bf215546Sopenharmony_ci{
589bf215546Sopenharmony_ci   unsigned int bits_to_pack = 0;
590bf215546Sopenharmony_ci   enc->bits_size += num_bits;
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci   while (num_bits > 0) {
593bf215546Sopenharmony_ci      unsigned int value_to_pack = value & (0xffffffff >> (32 - num_bits));
594bf215546Sopenharmony_ci      bits_to_pack =
595bf215546Sopenharmony_ci         num_bits > (32 - enc->bits_in_shifter) ? (32 - enc->bits_in_shifter) : num_bits;
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci      if (bits_to_pack < num_bits)
598bf215546Sopenharmony_ci         value_to_pack = value_to_pack >> (num_bits - bits_to_pack);
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci      enc->shifter |= value_to_pack << (32 - enc->bits_in_shifter - bits_to_pack);
601bf215546Sopenharmony_ci      num_bits -= bits_to_pack;
602bf215546Sopenharmony_ci      enc->bits_in_shifter += bits_to_pack;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci      while (enc->bits_in_shifter >= 8) {
605bf215546Sopenharmony_ci         unsigned char output_byte = (unsigned char)(enc->shifter >> 24);
606bf215546Sopenharmony_ci         enc->shifter <<= 8;
607bf215546Sopenharmony_ci         radeon_enc_emulation_prevention(enc, output_byte);
608bf215546Sopenharmony_ci         radeon_enc_output_one_byte(enc, output_byte);
609bf215546Sopenharmony_ci         enc->bits_in_shifter -= 8;
610bf215546Sopenharmony_ci         enc->bits_output += 8;
611bf215546Sopenharmony_ci      }
612bf215546Sopenharmony_ci   }
613bf215546Sopenharmony_ci}
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_civoid radeon_enc_reset(struct radeon_encoder *enc)
616bf215546Sopenharmony_ci{
617bf215546Sopenharmony_ci   enc->emulation_prevention = false;
618bf215546Sopenharmony_ci   enc->shifter = 0;
619bf215546Sopenharmony_ci   enc->bits_in_shifter = 0;
620bf215546Sopenharmony_ci   enc->bits_output = 0;
621bf215546Sopenharmony_ci   enc->num_zeros = 0;
622bf215546Sopenharmony_ci   enc->byte_index = 0;
623bf215546Sopenharmony_ci   enc->bits_size = 0;
624bf215546Sopenharmony_ci}
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_civoid radeon_enc_byte_align(struct radeon_encoder *enc)
627bf215546Sopenharmony_ci{
628bf215546Sopenharmony_ci   unsigned int num_padding_zeros = (32 - enc->bits_in_shifter) % 8;
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   if (num_padding_zeros > 0)
631bf215546Sopenharmony_ci      radeon_enc_code_fixed_bits(enc, 0, num_padding_zeros);
632bf215546Sopenharmony_ci}
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_civoid radeon_enc_flush_headers(struct radeon_encoder *enc)
635bf215546Sopenharmony_ci{
636bf215546Sopenharmony_ci   if (enc->bits_in_shifter != 0) {
637bf215546Sopenharmony_ci      unsigned char output_byte = (unsigned char)(enc->shifter >> 24);
638bf215546Sopenharmony_ci      radeon_enc_emulation_prevention(enc, output_byte);
639bf215546Sopenharmony_ci      radeon_enc_output_one_byte(enc, output_byte);
640bf215546Sopenharmony_ci      enc->bits_output += enc->bits_in_shifter;
641bf215546Sopenharmony_ci      enc->shifter = 0;
642bf215546Sopenharmony_ci      enc->bits_in_shifter = 0;
643bf215546Sopenharmony_ci      enc->num_zeros = 0;
644bf215546Sopenharmony_ci   }
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci   if (enc->byte_index > 0) {
647bf215546Sopenharmony_ci      enc->cs.current.cdw++;
648bf215546Sopenharmony_ci      enc->byte_index = 0;
649bf215546Sopenharmony_ci   }
650bf215546Sopenharmony_ci}
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_civoid radeon_enc_code_ue(struct radeon_encoder *enc, unsigned int value)
653bf215546Sopenharmony_ci{
654bf215546Sopenharmony_ci   int x = -1;
655bf215546Sopenharmony_ci   unsigned int ue_code = value + 1;
656bf215546Sopenharmony_ci   value += 1;
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci   while (value) {
659bf215546Sopenharmony_ci      value = (value >> 1);
660bf215546Sopenharmony_ci      x += 1;
661bf215546Sopenharmony_ci   }
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   unsigned int ue_length = (x << 1) + 1;
664bf215546Sopenharmony_ci   radeon_enc_code_fixed_bits(enc, ue_code, ue_length);
665bf215546Sopenharmony_ci}
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_civoid radeon_enc_code_se(struct radeon_encoder *enc, int value)
668bf215546Sopenharmony_ci{
669bf215546Sopenharmony_ci   unsigned int v = 0;
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   if (value != 0)
672bf215546Sopenharmony_ci      v = (value < 0 ? ((unsigned int)(0 - value) << 1) : (((unsigned int)(value) << 1) - 1));
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   radeon_enc_code_ue(enc, v);
675bf215546Sopenharmony_ci}
676