media: allegro: write vui parameters for HEVC

The vui parameters are optional. However, the vui data allows to specify
the color space of the encoded video. Write the vui parameters to make
sure that decoders are able to pick up the correct color space.

Also implement the necessary lookup functions to convert the values from
the V4L2 controls to the values specified in the hevc standard.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Michael Tretter 2021-09-08 14:03:55 +01:00 committed by Mauro Carvalho Chehab
parent 42fd280628
commit b35d3fea2a
2 changed files with 130 additions and 6 deletions

View File

@ -1762,7 +1762,10 @@ static ssize_t allegro_hevc_write_sps(struct allegro_channel *channel,
struct allegro_dev *dev = channel->dev;
struct nal_hevc_sps *sps;
struct nal_hevc_profile_tier_level *ptl;
struct nal_hevc_vui_parameters *vui;
struct nal_hevc_hrd_parameters *hrd;
ssize_t size;
unsigned int cpb_size;
unsigned int num_ref_frames = channel->num_ref_idx_l0;
s32 profile = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_profile);
s32 level = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_level);
@ -1815,6 +1818,50 @@ static ssize_t allegro_hevc_write_sps(struct allegro_channel *channel,
sps->sps_temporal_mvp_enabled_flag = channel->temporal_mvp_enable;
sps->strong_intra_smoothing_enabled_flag = channel->max_cu_size > 4;
sps->vui_parameters_present_flag = 1;
vui = &sps->vui;
vui->video_signal_type_present_flag = 1;
vui->video_format = 5; /* unspecified */
vui->video_full_range_flag = nal_hevc_full_range(channel->quantization);
vui->colour_description_present_flag = 1;
vui->colour_primaries = nal_hevc_color_primaries(channel->colorspace);
vui->transfer_characteristics = nal_hevc_transfer_characteristics(channel->colorspace,
channel->xfer_func);
vui->matrix_coeffs = nal_hevc_matrix_coeffs(channel->colorspace, channel->ycbcr_enc);
vui->chroma_loc_info_present_flag = 1;
vui->chroma_sample_loc_type_top_field = 0;
vui->chroma_sample_loc_type_bottom_field = 0;
vui->vui_timing_info_present_flag = 1;
vui->vui_num_units_in_tick = channel->framerate.denominator;
vui->vui_time_scale = channel->framerate.numerator;
vui->bitstream_restriction_flag = 1;
vui->motion_vectors_over_pic_boundaries_flag = 1;
vui->restricted_ref_pic_lists_flag = 1;
vui->log2_max_mv_length_horizontal = 15;
vui->log2_max_mv_length_vertical = 15;
vui->vui_hrd_parameters_present_flag = 1;
hrd = &vui->nal_hrd_parameters;
hrd->vcl_hrd_parameters_present_flag = 1;
hrd->initial_cpb_removal_delay_length_minus1 = 31;
hrd->au_cpb_removal_delay_length_minus1 = 30;
hrd->dpb_output_delay_length_minus1 = 30;
hrd->bit_rate_scale = ffs(channel->bitrate_peak) - 6;
hrd->vcl_hrd[0].bit_rate_value_minus1[0] =
(channel->bitrate_peak >> (6 + hrd->bit_rate_scale)) - 1;
cpb_size = v4l2_ctrl_g_ctrl(channel->mpeg_video_cpb_size) * 1000;
hrd->cpb_size_scale = ffs(cpb_size) - 4;
hrd->vcl_hrd[0].cpb_size_value_minus1[0] = (cpb_size >> (4 + hrd->cpb_size_scale)) - 1;
hrd->vcl_hrd[0].cbr_flag[0] = !v4l2_ctrl_g_ctrl(channel->mpeg_video_frame_rc_enable);
size = nal_hevc_write_sps(&dev->plat_dev->dev, dest, n, sps);
kfree(sps);

View File

@ -414,12 +414,89 @@ static inline int nal_hevc_level(enum v4l2_mpeg_video_hevc_level level)
}
}
int nal_range_from_v4l2(enum v4l2_quantization quantization);
int nal_color_primaries_from_v4l2(enum v4l2_colorspace colorspace);
int nal_transfer_characteristics_from_v4l2(enum v4l2_colorspace colorspace,
enum v4l2_xfer_func xfer_func);
int nal_matrix_coeffs_from_v4l2(enum v4l2_colorspace colorspace,
enum v4l2_ycbcr_encoding ycbcr_encoding);
static inline int nal_hevc_full_range(enum v4l2_quantization quantization)
{
switch (quantization) {
case V4L2_QUANTIZATION_FULL_RANGE:
return 1;
case V4L2_QUANTIZATION_LIM_RANGE:
return 0;
default:
break;
}
return 0;
}
static inline int nal_hevc_color_primaries(enum v4l2_colorspace colorspace)
{
switch (colorspace) {
case V4L2_COLORSPACE_SMPTE170M:
return 6;
case V4L2_COLORSPACE_SMPTE240M:
return 7;
case V4L2_COLORSPACE_REC709:
return 1;
case V4L2_COLORSPACE_470_SYSTEM_M:
return 4;
case V4L2_COLORSPACE_JPEG:
case V4L2_COLORSPACE_SRGB:
case V4L2_COLORSPACE_470_SYSTEM_BG:
return 5;
case V4L2_COLORSPACE_BT2020:
return 9;
case V4L2_COLORSPACE_DEFAULT:
case V4L2_COLORSPACE_OPRGB:
case V4L2_COLORSPACE_RAW:
case V4L2_COLORSPACE_DCI_P3:
default:
return 2;
}
}
static inline int nal_hevc_transfer_characteristics(enum v4l2_colorspace colorspace,
enum v4l2_xfer_func xfer_func)
{
if (xfer_func == V4L2_XFER_FUNC_DEFAULT)
xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(colorspace);
switch (xfer_func) {
case V4L2_XFER_FUNC_709:
return 6;
case V4L2_XFER_FUNC_SMPTE2084:
return 16;
case V4L2_XFER_FUNC_SRGB:
case V4L2_XFER_FUNC_OPRGB:
case V4L2_XFER_FUNC_NONE:
case V4L2_XFER_FUNC_DCI_P3:
case V4L2_XFER_FUNC_SMPTE240M:
default:
return 2;
}
}
static inline int nal_hevc_matrix_coeffs(enum v4l2_colorspace colorspace,
enum v4l2_ycbcr_encoding ycbcr_encoding)
{
if (ycbcr_encoding == V4L2_YCBCR_ENC_DEFAULT)
ycbcr_encoding = V4L2_MAP_YCBCR_ENC_DEFAULT(colorspace);
switch (ycbcr_encoding) {
case V4L2_YCBCR_ENC_601:
case V4L2_YCBCR_ENC_XV601:
return 5;
case V4L2_YCBCR_ENC_709:
case V4L2_YCBCR_ENC_XV709:
return 1;
case V4L2_YCBCR_ENC_BT2020:
return 9;
case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
return 10;
case V4L2_YCBCR_ENC_SMPTE240M:
default:
return 2;
}
}
ssize_t nal_hevc_write_vps(const struct device *dev,
void *dest, size_t n, struct nal_hevc_vps *vps);