radeon/vcn: program drm message buffer

Add a function to handle drm message buffer using input decryption parameters.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7006>
This commit is contained in:
Boyuan Zhang 2020-05-13 20:08:55 -04:00 committed by Pierre-Eric Pelloux-Prayer
parent ebbf40fa26
commit f20a20b1e3
1 changed files with 109 additions and 8 deletions

View File

@ -34,6 +34,7 @@
#include "util/u_video.h"
#include "vl/vl_mpeg12_decoder.h"
#include "vl/vl_probs_table.h"
#include "pspdecryptionparam.h"
#include <assert.h>
#include <stdio.h>
@ -550,6 +551,47 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec,
return result;
}
static void set_drm_keys(rvcn_dec_message_drm_t *drm, DECRYPT_PARAMETERS *decrypted)
{
int cbc = decrypted->u.s.cbc;
int ctr = decrypted->u.s.ctr;
int id = decrypted->u.s.drm_id;
int ekc = 1;
int data1 = 1;
int data2 = 1;
drm->drm_cmd = 0;
drm->drm_cntl = 0;
drm->drm_cntl = 1 << DRM_CNTL_BYPASS_SHIFT;
if (cbc || ctr) {
drm->drm_cntl = 0 << DRM_CNTL_BYPASS_SHIFT;
drm->drm_cmd |= 0xff << DRM_CMD_BYTE_MASK_SHIFT;
if (ctr)
drm->drm_cmd |= 0x00 << DRM_CMD_ALGORITHM_SHIFT;
else if (cbc)
drm->drm_cmd |= 0x02 << DRM_CMD_ALGORITHM_SHIFT;
drm->drm_cmd |= 1 << DRM_CMD_GEN_MASK_SHIFT;
drm->drm_cmd |= ekc << DRM_CMD_UNWRAP_KEY_SHIFT;
drm->drm_cmd |= 0 << DRM_CMD_OFFSET_SHIFT;
drm->drm_cmd |= data2 << DRM_CMD_CNT_DATA_SHIFT;
drm->drm_cmd |= data1 << DRM_CMD_CNT_KEY_SHIFT;
drm->drm_cmd |= ekc << DRM_CMD_KEY_SHIFT;
drm->drm_cmd |= id << DRM_CMD_SESSION_SEL_SHIFT;
if (ekc)
memcpy(drm->drm_wrapped_key, decrypted->encrypted_key, 16);
if (data1)
memcpy(drm->drm_key, decrypted->session_iv, 16);
if (data2)
memcpy(drm->drm_counter, decrypted->encrypted_iv, 16);
drm->drm_offset = 0;
}
}
static unsigned calc_ctx_size_h265_main(struct radeon_decoder *dec)
{
unsigned width = align(dec->base.width, VL_MACROBLOCK_WIDTH);
@ -796,29 +838,51 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture)
{
DECRYPT_PARAMETERS *decrypt = (DECRYPT_PARAMETERS *)picture->decrypt_key;
bool encrypted = (DECRYPT_PARAMETERS *)picture->protected_playback;
struct si_texture *luma = (struct si_texture *)((struct vl_video_buffer *)target)->resources[0];
struct si_texture *chroma =
(struct si_texture *)((struct vl_video_buffer *)target)->resources[1];
ASSERTED struct si_screen *sscreen = (struct si_screen *)dec->screen;
rvcn_dec_message_header_t *header;
rvcn_dec_message_index_t *index_drm;
rvcn_dec_message_index_t *index;
rvcn_dec_message_decode_t *decode;
unsigned sizes = 0, offset_decode, offset_codec;
unsigned int offset_drm;
void *codec;
rvcn_dec_message_drm_t *drm = NULL;
header = dec->msg;
sizes += sizeof(rvcn_dec_message_header_t);
index = (void *)header + sizeof(rvcn_dec_message_header_t);
sizes += sizeof(rvcn_dec_message_index_t);
if (encrypted) {
index_drm = (void*)header + sizeof(rvcn_dec_message_header_t);
sizes += sizeof(rvcn_dec_message_index_t);
index = (void*)index_drm + sizeof(rvcn_dec_message_index_t);
sizes += sizeof(rvcn_dec_message_index_t);
} else {
index = (void*)header + sizeof(rvcn_dec_message_header_t);
sizes += sizeof(rvcn_dec_message_index_t);
}
offset_decode = sizes;
decode = (void *)index + sizeof(rvcn_dec_message_index_t);
sizes += sizeof(rvcn_dec_message_decode_t);
if (encrypted) {
offset_drm = sizes;
drm = (void*)decode + sizeof(rvcn_dec_message_decode_t);
sizes += sizeof(rvcn_dec_message_drm_t);
codec = (void*)drm + sizeof(rvcn_dec_message_drm_t);
} else
codec = (void*)decode + sizeof(rvcn_dec_message_decode_t);
offset_codec = sizes;
codec = (void *)decode + sizeof(rvcn_dec_message_decode_t);
memset(dec->msg, 0, sizes);
header->header_size = sizeof(rvcn_dec_message_header_t);
header->total_size = sizes;
header->num_buffers = 2;
if (encrypted)
header->num_buffers = 3;
else
header->num_buffers = 2;
header->msg_type = RDECODE_MSG_DECODE;
header->stream_handle = dec->stream_handle;
header->status_report_feedback_number = dec->frame_number;
@ -827,6 +891,12 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
header->index[0].offset = offset_decode;
header->index[0].size = sizeof(rvcn_dec_message_decode_t);
header->index[0].filled = 0;
if (encrypted) {
index_drm->message_id = RDECODE_MESSAGE_DRM;
index_drm->offset = offset_drm;
index_drm->size = sizeof(rvcn_dec_message_drm_t);
index_drm->filled = 0;
}
index->offset = offset_codec;
index->size = sizeof(rvcn_dec_message_avc_t);
@ -843,7 +913,12 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
unsigned dpb_size = calc_dpb_size(dec);
bool r;
if (dpb_size) {
r = si_vid_create_buffer(dec->screen, &dec->dpb, dpb_size, PIPE_USAGE_DEFAULT);
if (encrypted) {
r = si_vid_create_tmz_buffer(dec->screen, &dec->dpb, dpb_size, PIPE_USAGE_DEFAULT);
} else {
r = si_vid_create_buffer(dec->screen, &dec->dpb, dpb_size, PIPE_USAGE_DEFAULT);
}
assert(encrypted == (bool)(dec->dpb.res->flags & RADEON_FLAG_ENCRYPTED));
if (!r) {
RVID_ERR("Can't allocated dpb.\n");
return NULL;
@ -857,7 +932,12 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
if (dec->stream_type == RDECODE_CODEC_H264_PERF) {
unsigned ctx_size = calc_ctx_size_h264_perf(dec);
bool r;
r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
if (encrypted) {
r = si_vid_create_tmz_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
} else {
r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
}
assert(encrypted == (bool)(dec->ctx.res->flags & RADEON_FLAG_ENCRYPTED));
if (!r) {
RVID_ERR("Can't allocated context buffer.\n");
@ -888,7 +968,11 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
if (dec->base.profile == PIPE_VIDEO_PROFILE_VP9_PROFILE2)
ctx_size += 8 * 2 * 4096;
r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
if (encrypted) {
r = si_vid_create_tmz_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
} else {
r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
}
if (!r) {
RVID_ERR("Can't allocated context buffer.\n");
return NULL;
@ -903,15 +987,27 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
dec->bs_ptr = NULL;
} else if (fmt == PIPE_VIDEO_FORMAT_HEVC) {
unsigned ctx_size;
bool r;
if (dec->base.profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10)
ctx_size = calc_ctx_size_h265_main10(dec, (struct pipe_h265_picture_desc *)picture);
else
ctx_size = calc_ctx_size_h265_main(dec);
if (!si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT))
if (encrypted) {
r = si_vid_create_tmz_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
} else {
r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT);
}
if (!r) {
RVID_ERR("Can't allocated context buffer.\n");
return NULL;
}
si_vid_clear_buffer(dec->base.context, &dec->ctx);
}
}
if (encrypted != dec->ws->cs_is_secure(dec->cs)) {
dec->ws->cs_flush(dec->cs, RADEON_FLUSH_TOGGLE_SECURE_SUBMISSION, NULL);
}
decode->dpb_size = dec->dpb.res->buf->size;
decode->dt_size = si_resource(((struct vl_video_buffer *)target)->resources[0])->buf->size +
@ -953,6 +1049,11 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec,
decode->dt_chroma_bottom_offset = decode->dt_chroma_top_offset;
}
if (encrypted) {
assert(sscreen->info.has_tmz_support);
set_drm_keys(drm, decrypt);
}
switch (u_reduce_video_profile(picture->profile)) {
case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
rvcn_dec_message_avc_t avc = get_h264_msg(dec, (struct pipe_h264_picture_desc *)picture);