1/************************************************************************** 2 * 3 * Copyright 2018 Advanced Micro Devices, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "radeon_uvd_enc.h" 29 30#include "pipe/p_video_codec.h" 31#include "radeon_video.h" 32#include "radeonsi/si_pipe.h" 33#include "util/u_memory.h" 34#include "util/u_video.h" 35#include "vl/vl_video_buffer.h" 36 37#include <stdio.h> 38 39#define UVD_HEVC_LEVEL_1 30 40#define UVD_HEVC_LEVEL_2 60 41#define UVD_HEVC_LEVEL_2_1 63 42#define UVD_HEVC_LEVEL_3 90 43#define UVD_HEVC_LEVEL_3_1 93 44#define UVD_HEVC_LEVEL_4 120 45#define UVD_HEVC_LEVEL_4_1 123 46#define UVD_HEVC_LEVEL_5 150 47#define UVD_HEVC_LEVEL_5_1 153 48#define UVD_HEVC_LEVEL_5_2 156 49#define UVD_HEVC_LEVEL_6 180 50#define UVD_HEVC_LEVEL_6_1 183 51#define UVD_HEVC_LEVEL_6_2 186 52 53static void radeon_uvd_enc_get_param(struct radeon_uvd_encoder *enc, 54 struct pipe_h265_enc_picture_desc *pic) 55{ 56 enc->enc_pic.picture_type = pic->picture_type; 57 enc->enc_pic.frame_num = pic->frame_num; 58 enc->enc_pic.pic_order_cnt = pic->pic_order_cnt; 59 enc->enc_pic.pic_order_cnt_type = pic->pic_order_cnt_type; 60 enc->enc_pic.not_referenced = pic->not_referenced; 61 enc->enc_pic.is_iframe = (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) || 62 (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_I); 63 64 if (pic->seq.conformance_window_flag) { 65 enc->enc_pic.crop_left = pic->seq.conf_win_left_offset; 66 enc->enc_pic.crop_right = pic->seq.conf_win_right_offset; 67 enc->enc_pic.crop_top = pic->seq.conf_win_top_offset; 68 enc->enc_pic.crop_bottom = pic->seq.conf_win_bottom_offset; 69 } else { 70 enc->enc_pic.crop_left = 0; 71 enc->enc_pic.crop_right = (align(enc->base.width, 16) - enc->base.width) / 2; 72 enc->enc_pic.crop_top = 0; 73 enc->enc_pic.crop_bottom = (align(enc->base.height, 16) - enc->base.height) / 2; 74 } 75 76 enc->enc_pic.general_tier_flag = pic->seq.general_tier_flag; 77 enc->enc_pic.general_profile_idc = pic->seq.general_profile_idc; 78 enc->enc_pic.general_level_idc = pic->seq.general_level_idc; 79 enc->enc_pic.max_poc = MAX2(16, util_next_power_of_two(pic->seq.intra_period)); 80 enc->enc_pic.log2_max_poc = 0; 81 for (int i = enc->enc_pic.max_poc; i != 0; enc->enc_pic.log2_max_poc++) 82 i = (i >> 1); 83 enc->enc_pic.chroma_format_idc = pic->seq.chroma_format_idc; 84 enc->enc_pic.pic_width_in_luma_samples = pic->seq.pic_width_in_luma_samples; 85 enc->enc_pic.pic_height_in_luma_samples = pic->seq.pic_height_in_luma_samples; 86 enc->enc_pic.log2_diff_max_min_luma_coding_block_size = 87 pic->seq.log2_diff_max_min_luma_coding_block_size; 88 enc->enc_pic.log2_min_transform_block_size_minus2 = 89 pic->seq.log2_min_transform_block_size_minus2; 90 enc->enc_pic.log2_diff_max_min_transform_block_size = 91 pic->seq.log2_diff_max_min_transform_block_size; 92 enc->enc_pic.max_transform_hierarchy_depth_inter = pic->seq.max_transform_hierarchy_depth_inter; 93 enc->enc_pic.max_transform_hierarchy_depth_intra = pic->seq.max_transform_hierarchy_depth_intra; 94 enc->enc_pic.log2_parallel_merge_level_minus2 = pic->pic.log2_parallel_merge_level_minus2; 95 enc->enc_pic.bit_depth_luma_minus8 = pic->seq.bit_depth_luma_minus8; 96 enc->enc_pic.bit_depth_chroma_minus8 = pic->seq.bit_depth_chroma_minus8; 97 enc->enc_pic.nal_unit_type = pic->pic.nal_unit_type; 98 enc->enc_pic.max_num_merge_cand = pic->slice.max_num_merge_cand; 99 enc->enc_pic.sample_adaptive_offset_enabled_flag = pic->seq.sample_adaptive_offset_enabled_flag; 100 enc->enc_pic.pcm_enabled_flag = 0; /*HW not support PCM */ 101 enc->enc_pic.sps_temporal_mvp_enabled_flag = pic->seq.sps_temporal_mvp_enabled_flag; 102} 103 104static void flush(struct radeon_uvd_encoder *enc) 105{ 106 enc->ws->cs_flush(&enc->cs, PIPE_FLUSH_ASYNC, NULL); 107} 108 109static void radeon_uvd_enc_flush(struct pipe_video_codec *encoder) 110{ 111 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder; 112 flush(enc); 113} 114 115static void radeon_uvd_enc_cs_flush(void *ctx, unsigned flags, struct pipe_fence_handle **fence) 116{ 117 // just ignored 118} 119 120static unsigned get_cpb_num(struct radeon_uvd_encoder *enc) 121{ 122 unsigned w = align(enc->base.width, 16) / 16; 123 unsigned h = align(enc->base.height, 16) / 16; 124 unsigned dpb; 125 126 switch (enc->base.level) { 127 case UVD_HEVC_LEVEL_1: 128 dpb = 36864; 129 break; 130 131 case UVD_HEVC_LEVEL_2: 132 dpb = 122880; 133 break; 134 135 case UVD_HEVC_LEVEL_2_1: 136 dpb = 245760; 137 break; 138 139 case UVD_HEVC_LEVEL_3: 140 dpb = 552960; 141 break; 142 143 case UVD_HEVC_LEVEL_3_1: 144 dpb = 983040; 145 break; 146 147 case UVD_HEVC_LEVEL_4: 148 case UVD_HEVC_LEVEL_4_1: 149 dpb = 2228224; 150 break; 151 152 case UVD_HEVC_LEVEL_5: 153 case UVD_HEVC_LEVEL_5_1: 154 case UVD_HEVC_LEVEL_5_2: 155 dpb = 8912896; 156 break; 157 158 case UVD_HEVC_LEVEL_6: 159 case UVD_HEVC_LEVEL_6_1: 160 case UVD_HEVC_LEVEL_6_2: 161 default: 162 dpb = 35651584; 163 break; 164 } 165 166 return MIN2(dpb / (w * h), 16); 167} 168 169static void radeon_uvd_enc_begin_frame(struct pipe_video_codec *encoder, 170 struct pipe_video_buffer *source, 171 struct pipe_picture_desc *picture) 172{ 173 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder; 174 struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source; 175 176 radeon_uvd_enc_get_param(enc, (struct pipe_h265_enc_picture_desc *)picture); 177 178 enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma); 179 enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma); 180 181 enc->need_feedback = false; 182 183 if (!enc->stream_handle) { 184 struct rvid_buffer fb; 185 enc->stream_handle = si_vid_alloc_stream_handle(); 186 enc->si = CALLOC_STRUCT(rvid_buffer); 187 si_vid_create_buffer(enc->screen, enc->si, 128 * 1024, PIPE_USAGE_STAGING); 188 si_vid_create_buffer(enc->screen, &fb, 4096, PIPE_USAGE_STAGING); 189 enc->fb = &fb; 190 enc->begin(enc, picture); 191 flush(enc); 192 si_vid_destroy_buffer(&fb); 193 } 194} 195 196static void radeon_uvd_enc_encode_bitstream(struct pipe_video_codec *encoder, 197 struct pipe_video_buffer *source, 198 struct pipe_resource *destination, void **fb) 199{ 200 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder; 201 enc->get_buffer(destination, &enc->bs_handle, NULL); 202 enc->bs_size = destination->width0; 203 204 *fb = enc->fb = CALLOC_STRUCT(rvid_buffer); 205 206 if (!si_vid_create_buffer(enc->screen, enc->fb, 4096, PIPE_USAGE_STAGING)) { 207 RVID_ERR("Can't create feedback buffer.\n"); 208 return; 209 } 210 211 enc->need_feedback = true; 212 enc->encode(enc); 213} 214 215static void radeon_uvd_enc_end_frame(struct pipe_video_codec *encoder, 216 struct pipe_video_buffer *source, 217 struct pipe_picture_desc *picture) 218{ 219 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder; 220 flush(enc); 221} 222 223static void radeon_uvd_enc_destroy(struct pipe_video_codec *encoder) 224{ 225 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder; 226 227 if (enc->stream_handle) { 228 struct rvid_buffer fb; 229 enc->need_feedback = false; 230 si_vid_create_buffer(enc->screen, &fb, 512, PIPE_USAGE_STAGING); 231 enc->fb = &fb; 232 enc->destroy(enc); 233 flush(enc); 234 si_vid_destroy_buffer(&fb); 235 } 236 237 si_vid_destroy_buffer(&enc->cpb); 238 enc->ws->cs_destroy(&enc->cs); 239 FREE(enc); 240} 241 242static void radeon_uvd_enc_get_feedback(struct pipe_video_codec *encoder, void *feedback, 243 unsigned *size) 244{ 245 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder; 246 struct rvid_buffer *fb = feedback; 247 248 if (NULL != size) { 249 radeon_uvd_enc_feedback_t *fb_data = (radeon_uvd_enc_feedback_t *)enc->ws->buffer_map( 250 enc->ws, fb->res->buf, &enc->cs, PIPE_MAP_READ_WRITE | RADEON_MAP_TEMPORARY); 251 252 if (!fb_data->status) 253 *size = fb_data->bitstream_size; 254 else 255 *size = 0; 256 enc->ws->buffer_unmap(enc->ws, fb->res->buf); 257 } 258 259 si_vid_destroy_buffer(fb); 260 FREE(fb); 261} 262 263struct pipe_video_codec *radeon_uvd_create_encoder(struct pipe_context *context, 264 const struct pipe_video_codec *templ, 265 struct radeon_winsys *ws, 266 radeon_uvd_enc_get_buffer get_buffer) 267{ 268 struct si_screen *sscreen = (struct si_screen *)context->screen; 269 struct si_context *sctx = (struct si_context *)context; 270 struct radeon_uvd_encoder *enc; 271 struct pipe_video_buffer *tmp_buf, templat = {}; 272 struct radeon_surf *tmp_surf; 273 unsigned cpb_size; 274 275 if (!si_radeon_uvd_enc_supported(sscreen)) { 276 RVID_ERR("Unsupported UVD ENC fw version loaded!\n"); 277 return NULL; 278 } 279 280 enc = CALLOC_STRUCT(radeon_uvd_encoder); 281 282 if (!enc) 283 return NULL; 284 285 enc->base = *templ; 286 enc->base.context = context; 287 enc->base.destroy = radeon_uvd_enc_destroy; 288 enc->base.begin_frame = radeon_uvd_enc_begin_frame; 289 enc->base.encode_bitstream = radeon_uvd_enc_encode_bitstream; 290 enc->base.end_frame = radeon_uvd_enc_end_frame; 291 enc->base.flush = radeon_uvd_enc_flush; 292 enc->base.get_feedback = radeon_uvd_enc_get_feedback; 293 enc->get_buffer = get_buffer; 294 enc->bits_in_shifter = 0; 295 enc->screen = context->screen; 296 enc->ws = ws; 297 298 if (!ws->cs_create(&enc->cs, sctx->ctx, AMD_IP_UVD_ENC, radeon_uvd_enc_cs_flush, enc, false)) { 299 RVID_ERR("Can't get command submission context.\n"); 300 goto error; 301 } 302 303 struct rvid_buffer si; 304 si_vid_create_buffer(enc->screen, &si, 128 * 1024, PIPE_USAGE_STAGING); 305 enc->si = &si; 306 307 templat.buffer_format = PIPE_FORMAT_NV12; 308 templat.width = enc->base.width; 309 templat.height = enc->base.height; 310 templat.interlaced = false; 311 312 if (!(tmp_buf = context->create_video_buffer(context, &templat))) { 313 RVID_ERR("Can't create video buffer.\n"); 314 goto error; 315 } 316 317 enc->cpb_num = get_cpb_num(enc); 318 319 if (!enc->cpb_num) 320 goto error; 321 322 get_buffer(((struct vl_video_buffer *)tmp_buf)->resources[0], NULL, &tmp_surf); 323 324 cpb_size = (sscreen->info.gfx_level < GFX9) 325 ? align(tmp_surf->u.legacy.level[0].nblk_x * tmp_surf->bpe, 128) * 326 align(tmp_surf->u.legacy.level[0].nblk_y, 32) 327 : align(tmp_surf->u.gfx9.surf_pitch * tmp_surf->bpe, 256) * 328 align(tmp_surf->u.gfx9.surf_height, 32); 329 330 cpb_size = cpb_size * 3 / 2; 331 cpb_size = cpb_size * enc->cpb_num; 332 tmp_buf->destroy(tmp_buf); 333 334 if (!si_vid_create_buffer(enc->screen, &enc->cpb, cpb_size, PIPE_USAGE_DEFAULT)) { 335 RVID_ERR("Can't create CPB buffer.\n"); 336 goto error; 337 } 338 339 radeon_uvd_enc_1_1_init(enc); 340 341 return &enc->base; 342 343error: 344 enc->ws->cs_destroy(&enc->cs); 345 346 si_vid_destroy_buffer(&enc->cpb); 347 348 FREE(enc); 349 return NULL; 350} 351 352bool si_radeon_uvd_enc_supported(struct si_screen *sscreen) 353{ 354 return sscreen->info.ip[AMD_IP_UVD_ENC].num_queues; 355} 356