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 <stdio.h> 29 30#include "pipe/p_video_codec.h" 31 32#include "util/u_video.h" 33#include "util/u_memory.h" 34 35#include "vl/vl_video_buffer.h" 36 37#include "radeonsi/si_pipe.h" 38#include "radeon_video.h" 39#include "radeon_uvd_enc.h" 40 41#define UVD_HEVC_LEVEL_1 30 42#define UVD_HEVC_LEVEL_2 60 43#define UVD_HEVC_LEVEL_2_1 63 44#define UVD_HEVC_LEVEL_3 90 45#define UVD_HEVC_LEVEL_3_1 93 46#define UVD_HEVC_LEVEL_4 120 47#define UVD_HEVC_LEVEL_4_1 123 48#define UVD_HEVC_LEVEL_5 150 49#define UVD_HEVC_LEVEL_5_1 153 50#define UVD_HEVC_LEVEL_5_2 156 51#define UVD_HEVC_LEVEL_6 180 52#define UVD_HEVC_LEVEL_6_1 183 53#define UVD_HEVC_LEVEL_6_2 186 54 55static void 56radeon_uvd_enc_get_param(struct radeon_uvd_encoder *enc, 57 struct pipe_h265_enc_picture_desc *pic) 58{ 59 enc->enc_pic.picture_type = pic->picture_type; 60 enc->enc_pic.frame_num = pic->frame_num; 61 enc->enc_pic.pic_order_cnt = pic->pic_order_cnt; 62 enc->enc_pic.pic_order_cnt_type = pic->pic_order_cnt_type; 63 enc->enc_pic.not_referenced = pic->not_referenced; 64 enc->enc_pic.is_iframe = 65 (pic->picture_type == PIPE_H265_ENC_PICTURE_TYPE_IDR) 66 || (pic->picture_type == PIPE_H265_ENC_PICTURE_TYPE_I); 67 enc->enc_pic.crop_left = 0; 68 enc->enc_pic.crop_right = 69 (align(enc->base.width, 16) - enc->base.width) / 2; 70 enc->enc_pic.crop_top = 0; 71 enc->enc_pic.crop_bottom = 72 (align(enc->base.height, 16) - enc->base.height) / 2; 73 enc->enc_pic.general_tier_flag = pic->seq.general_tier_flag; 74 enc->enc_pic.general_profile_idc = pic->seq.general_profile_idc; 75 enc->enc_pic.general_level_idc = pic->seq.general_level_idc; 76 enc->enc_pic.max_poc = 77 MAX2(16, util_next_power_of_two(pic->seq.intra_period)); 78 enc->enc_pic.log2_max_poc = 0; 79 for (int i = enc->enc_pic.max_poc; i != 0; enc->enc_pic.log2_max_poc++) 80 i = (i >> 1); 81 enc->enc_pic.chroma_format_idc = pic->seq.chroma_format_idc; 82 enc->enc_pic.pic_width_in_luma_samples = 83 pic->seq.pic_width_in_luma_samples; 84 enc->enc_pic.pic_height_in_luma_samples = 85 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 = 93 pic->seq.max_transform_hierarchy_depth_inter; 94 enc->enc_pic.max_transform_hierarchy_depth_intra = 95 pic->seq.max_transform_hierarchy_depth_intra; 96 enc->enc_pic.log2_parallel_merge_level_minus2 = 97 pic->pic.log2_parallel_merge_level_minus2; 98 enc->enc_pic.bit_depth_luma_minus8 = pic->seq.bit_depth_luma_minus8; 99 enc->enc_pic.bit_depth_chroma_minus8 = pic->seq.bit_depth_chroma_minus8; 100 enc->enc_pic.nal_unit_type = pic->pic.nal_unit_type; 101 enc->enc_pic.max_num_merge_cand = pic->slice.max_num_merge_cand; 102 enc->enc_pic.sample_adaptive_offset_enabled_flag = 103 pic->seq.sample_adaptive_offset_enabled_flag; 104 enc->enc_pic.pcm_enabled_flag = 0; /*HW not support PCM */ 105 enc->enc_pic.sps_temporal_mvp_enabled_flag = 106 pic->seq.sps_temporal_mvp_enabled_flag; 107} 108 109static void 110flush(struct radeon_uvd_encoder *enc) 111{ 112 enc->ws->cs_flush(enc->cs, PIPE_FLUSH_ASYNC, NULL); 113} 114 115static void 116radeon_uvd_enc_flush(struct pipe_video_codec *encoder) 117{ 118 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *) encoder; 119 flush(enc); 120} 121 122static void 123radeon_uvd_enc_cs_flush(void *ctx, unsigned flags, 124 struct pipe_fence_handle **fence) 125{ 126 // just ignored 127} 128 129static unsigned 130get_cpb_num(struct radeon_uvd_encoder *enc) 131{ 132 unsigned w = align(enc->base.width, 16) / 16; 133 unsigned h = align(enc->base.height, 16) / 16; 134 unsigned dpb; 135 136 switch (enc->base.level) { 137 case UVD_HEVC_LEVEL_1: 138 dpb = 36864; 139 break; 140 141 case UVD_HEVC_LEVEL_2: 142 dpb = 122880; 143 break; 144 145 case UVD_HEVC_LEVEL_2_1: 146 dpb = 245760; 147 break; 148 149 case UVD_HEVC_LEVEL_3: 150 dpb = 552960; 151 break; 152 153 case UVD_HEVC_LEVEL_3_1: 154 dpb = 983040; 155 break; 156 157 case UVD_HEVC_LEVEL_4: 158 case UVD_HEVC_LEVEL_4_1: 159 dpb = 2228224; 160 break; 161 162 case UVD_HEVC_LEVEL_5: 163 case UVD_HEVC_LEVEL_5_1: 164 case UVD_HEVC_LEVEL_5_2: 165 dpb = 8912896; 166 break; 167 168 case UVD_HEVC_LEVEL_6: 169 case UVD_HEVC_LEVEL_6_1: 170 case UVD_HEVC_LEVEL_6_2: 171 default: 172 dpb = 35651584; 173 break; 174 } 175 176 return MIN2(dpb / (w * h), 16); 177} 178 179static void 180radeon_uvd_enc_begin_frame(struct pipe_video_codec *encoder, 181 struct pipe_video_buffer *source, 182 struct pipe_picture_desc *picture) 183{ 184 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *) encoder; 185 struct vl_video_buffer *vid_buf = (struct vl_video_buffer *) source; 186 187 radeon_uvd_enc_get_param(enc, 188 (struct pipe_h265_enc_picture_desc *) picture); 189 190 enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma); 191 enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma); 192 193 enc->need_feedback = false; 194 195 if (!enc->stream_handle) { 196 struct rvid_buffer fb; 197 enc->stream_handle = si_vid_alloc_stream_handle(); 198 enc->si = CALLOC_STRUCT(rvid_buffer); 199 si_vid_create_buffer(enc->screen, enc->si, 128 * 1024, 200 PIPE_USAGE_STAGING); 201 si_vid_create_buffer(enc->screen, &fb, 4096, PIPE_USAGE_STAGING); 202 enc->fb = &fb; 203 enc->begin(enc, picture); 204 flush(enc); 205 si_vid_destroy_buffer(&fb); 206 } 207} 208 209static void 210radeon_uvd_enc_encode_bitstream(struct pipe_video_codec *encoder, 211 struct pipe_video_buffer *source, 212 struct pipe_resource *destination, void **fb) 213{ 214 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *) encoder; 215 enc->get_buffer(destination, &enc->bs_handle, NULL); 216 enc->bs_size = destination->width0; 217 218 *fb = enc->fb = CALLOC_STRUCT(rvid_buffer); 219 220 if (!si_vid_create_buffer(enc->screen, enc->fb, 4096, PIPE_USAGE_STAGING)) { 221 RVID_ERR("Can't create feedback buffer.\n"); 222 return; 223 } 224 225 enc->need_feedback = true; 226 enc->encode(enc); 227} 228 229static void 230radeon_uvd_enc_end_frame(struct pipe_video_codec *encoder, 231 struct pipe_video_buffer *source, 232 struct pipe_picture_desc *picture) 233{ 234 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *) encoder; 235 flush(enc); 236} 237 238static void 239radeon_uvd_enc_destroy(struct pipe_video_codec *encoder) 240{ 241 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *) encoder; 242 243 if (enc->stream_handle) { 244 struct rvid_buffer fb; 245 enc->need_feedback = false; 246 si_vid_create_buffer(enc->screen, &fb, 512, PIPE_USAGE_STAGING); 247 enc->fb = &fb; 248 enc->destroy(enc); 249 flush(enc); 250 si_vid_destroy_buffer(&fb); 251 } 252 253 si_vid_destroy_buffer(&enc->cpb); 254 enc->ws->cs_destroy(enc->cs); 255 FREE(enc); 256} 257 258static void 259radeon_uvd_enc_get_feedback(struct pipe_video_codec *encoder, 260 void *feedback, unsigned *size) 261{ 262 struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *) encoder; 263 struct rvid_buffer *fb = feedback; 264 265 if (NULL != size) { 266 radeon_uvd_enc_feedback_t *fb_data = 267 (radeon_uvd_enc_feedback_t *) enc->ws->buffer_map( 268 fb->res->buf, enc->cs, 269 PIPE_TRANSFER_READ_WRITE | RADEON_TRANSFER_TEMPORARY); 270 271 if (!fb_data->status) 272 *size = fb_data->bitstream_size; 273 else 274 *size = 0; 275 enc->ws->buffer_unmap(fb->res->buf); 276 } 277 278 si_vid_destroy_buffer(fb); 279 FREE(fb); 280} 281 282struct pipe_video_codec * 283radeon_uvd_create_encoder(struct pipe_context *context, 284 const struct pipe_video_codec *templ, 285 struct radeon_winsys *ws, 286 radeon_uvd_enc_get_buffer get_buffer) 287{ 288 struct si_screen *sscreen = (struct si_screen *) context->screen; 289 struct si_context *sctx = (struct si_context *) context; 290 struct radeon_uvd_encoder *enc; 291 struct pipe_video_buffer *tmp_buf, templat = { }; 292 struct radeon_surf *tmp_surf; 293 unsigned cpb_size; 294 295 if (!si_radeon_uvd_enc_supported(sscreen)) { 296 RVID_ERR("Unsupported UVD ENC fw version loaded!\n"); 297 return NULL; 298 } 299 300 enc = CALLOC_STRUCT(radeon_uvd_encoder); 301 302 if (!enc) 303 return NULL; 304 305 enc->base = *templ; 306 enc->base.context = context; 307 enc->base.destroy = radeon_uvd_enc_destroy; 308 enc->base.begin_frame = radeon_uvd_enc_begin_frame; 309 enc->base.encode_bitstream = radeon_uvd_enc_encode_bitstream; 310 enc->base.end_frame = radeon_uvd_enc_end_frame; 311 enc->base.flush = radeon_uvd_enc_flush; 312 enc->base.get_feedback = radeon_uvd_enc_get_feedback; 313 enc->get_buffer = get_buffer; 314 enc->bits_in_shifter = 0; 315 enc->screen = context->screen; 316 enc->ws = ws; 317 enc->cs = 318 ws->cs_create(sctx->ctx, RING_UVD_ENC, radeon_uvd_enc_cs_flush, enc, false); 319 320 if (!enc->cs) { 321 RVID_ERR("Can't get command submission context.\n"); 322 goto error; 323 } 324 325 struct rvid_buffer si; 326 si_vid_create_buffer(enc->screen, &si, 128 * 1024, PIPE_USAGE_STAGING); 327 enc->si = &si; 328 329 templat.buffer_format = PIPE_FORMAT_NV12; 330 templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 331 templat.width = enc->base.width; 332 templat.height = enc->base.height; 333 templat.interlaced = false; 334 335 if (!(tmp_buf = context->create_video_buffer(context, &templat))) { 336 RVID_ERR("Can't create video buffer.\n"); 337 goto error; 338 } 339 340 enc->cpb_num = get_cpb_num(enc); 341 342 if (!enc->cpb_num) 343 goto error; 344 345 get_buffer(((struct vl_video_buffer *) tmp_buf)->resources[0], NULL, 346 &tmp_surf); 347 348 cpb_size = (sscreen->info.chip_class < GFX9) ? 349 align(tmp_surf->u.legacy.level[0].nblk_x * tmp_surf->bpe, 128) * 350 align(tmp_surf->u.legacy.level[0].nblk_y, 32) : 351 align(tmp_surf->u.gfx9.surf_pitch * tmp_surf->bpe, 256) * 352 align(tmp_surf->u.gfx9.surf_height, 32); 353 354 cpb_size = cpb_size * 3 / 2; 355 cpb_size = cpb_size * enc->cpb_num; 356 tmp_buf->destroy(tmp_buf); 357 358 if (!si_vid_create_buffer 359 (enc->screen, &enc->cpb, cpb_size, PIPE_USAGE_DEFAULT)) { 360 RVID_ERR("Can't create CPB buffer.\n"); 361 goto error; 362 } 363 364 radeon_uvd_enc_1_1_init(enc); 365 366 return &enc->base; 367 368 error: 369 if (enc->cs) 370 enc->ws->cs_destroy(enc->cs); 371 372 si_vid_destroy_buffer(&enc->cpb); 373 374 FREE(enc); 375 return NULL; 376} 377 378bool 379si_radeon_uvd_enc_supported(struct si_screen * sscreen) 380{ 381 return (sscreen->info.uvd_enc_supported); 382} 383