Skip to content
Snippets Groups Projects
Commit a4286c45 authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Commit Bot
Browse files

libv4lplugins: Change h264 level to a specified one

An app can specify the h264 stream of the encoded stream by
calling VIDIOC_S_EXT_CTRL with V4L2_CID_MPEG_VIDEO_H264_LEVEL.
However, libv4lplugins ignores the specified level the h264 level
is always 4.0. The plugin must change the level to the level
set by app.

BUG=chromium:1036219, chromium:1036220, b:146854692
TEST=webrtc.RTCPeerConnectionAccelUsed.enc_h264 on kevin
TEST=android.media.cts.MediaRecorderTest#testProfileAvcBaselineLevel1

Change-Id: I6c010af8862624e37418b86458a7f9df8aa2c868
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/libv4lplugins/+/1980599


Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Tested-by: default avatarHirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Reviewed-by: default avatarChih-Yu Huang <akahuang@chromium.org>
parent 3fa6081e
No related branches found
No related tags found
No related merge requests found
......@@ -199,6 +199,8 @@ static pthread_once_t g_get_log_level_once = PTHREAD_ONCE_INIT;
/* Returns true when the H264 profile is supported. */
static bool is_supported_h264_profile(uint8_t profile);
/* Returns true when the H264 true is supported. */
static bool is_supported_h264_level(uint8_t level);
static void *plugin_init(int fd)
{
......@@ -508,7 +510,13 @@ static int ioctl_s_ext_ctrls_locked(struct encoder_context *ctx, int fd,
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
if (!is_supported_h264_profile(ext_ctrls->controls[i].value))
return -EINVAL;
ctx->init_param.h264e.h264_profile =
ctx->init_param.h264e.v4l2_h264_profile =
ext_ctrls->controls[i].value;
break;
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
if (!is_supported_h264_level(ext_ctrls->controls[i].value))
return -EINVAL;
ctx->init_param.h264e.v4l2_h264_level =
ext_ctrls->controls[i].value;
break;
default:
......@@ -770,6 +778,9 @@ static int initialize_libvpu(struct encoder_context *ctx, int fd)
{
struct rk_vepu_init_param init_param;
memset(&init_param, 0, sizeof(init_param));
/* The default value of h264 level is 4.0. */
init_param.h264e.v4l2_h264_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
/* Get the input format. */
struct v4l2_format format;
......@@ -939,6 +950,11 @@ static bool is_supported_h264_profile(uint8_t profile) {
profile == V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
}
static bool is_supported_h264_level(uint8_t level) {
// RK3399 is capable of encoding h264 whose level is 4.1 and lower.
return level <= V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
}
PLUGIN_PUBLIC const struct libv4l_dev_ops libv4l2_plugin = {
.init = &plugin_init,
.close = &plugin_close,
......
......@@ -33,9 +33,50 @@ const int32_t h264e_qp_tbl[2][11] = {
const int baseline_idc = 66;
const int main_idc = 77;
static void h264e_init_sps(struct v4l2_plugin_h264_sps *sps, uint8_t profile)
static uint8_t v4l2_level_to_h264_level(uint8_t level) {
switch (level) {
case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
return H264ENC_LEVEL_1;
case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
return H264ENC_LEVEL_1_b;
case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
return H264ENC_LEVEL_1_1;
case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
return H264ENC_LEVEL_1_2;
case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
return H264ENC_LEVEL_1_3;
case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
return H264ENC_LEVEL_2;
case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
return H264ENC_LEVEL_2_1;
case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
return H264ENC_LEVEL_2_2;
case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
return H264ENC_LEVEL_3;
case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
return H264ENC_LEVEL_3_1;
case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
return H264ENC_LEVEL_3_2;
case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
return H264ENC_LEVEL_4_0;
case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
return H264ENC_LEVEL_4_1;
case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
return 42;
case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
return 50;
case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
return 51;
default:
fprintf(stderr, "Unknown h264 level=%d, use 4.0", (int) level);
return H264ENC_LEVEL_4_0;
};
}
static void h264e_init_sps(struct v4l2_plugin_h264_sps *sps, uint8_t v4l2_profile, uint8_t v4l2_level)
{
switch(profile) {
switch(v4l2_profile) {
case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
sps->profile_idc = baseline_idc;
......@@ -54,9 +95,7 @@ static void h264e_init_sps(struct v4l2_plugin_h264_sps *sps, uint8_t profile)
/* if level idc == 1b, constraint_set3_flag need to be set true */
sps->constraint_set3_flag = 0;
/* if level max than 31, we prefer disable 4x4 mv mode
to limit max mv count per 2mb */
sps->level_idc = H264ENC_LEVEL_4_0;
sps->level_idc = v4l2_level_to_h264_level(v4l2_level);
sps->seq_parameter_set_id = 0;
/* fixed values limited by hardware */
......@@ -79,13 +118,13 @@ static void h264e_init_sps(struct v4l2_plugin_h264_sps *sps, uint8_t profile)
sps->vui_parameters_present_flag = 1;
}
static void h264e_init_pps(struct v4l2_plugin_h264_pps *pps, uint8_t profile)
static void h264e_init_pps(struct v4l2_plugin_h264_pps *pps, uint8_t v4l2_profile)
{
pps->pic_parameter_set_id = 0;
pps->seq_parameter_set_id = 0;
pps->entropy_coding_mode_flag = 0;
if (profile >= V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) {
if (v4l2_profile >= V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) {
/* enable cabac coding need set profile_idc large than 77 */
pps->entropy_coding_mode_flag = 1;
}
......@@ -413,15 +452,15 @@ static int h264e_init(struct rk_venc *ictx,
ictx->fmt = ENC_FORMAT_H264;
ctx->h264_sps_pps_before_idr = param->h264e.h264_sps_pps_before_idr;
ctx->h264_profile = param->h264e.h264_profile;
ctx->width = param->width;
ctx->height = param->height;
ctx->slice_size_mb_rows = 0;
ctx->frm_in_gop = 0;
h264e_init_sps(&ctx->sps, ctx->h264_profile);
h264e_init_pps(&ctx->pps, ctx->h264_profile);
h264e_init_sps(&ctx->sps, param->h264e.v4l2_h264_profile,
param->h264e.v4l2_h264_level);
h264e_init_pps(&ctx->pps, param->h264e.v4l2_h264_profile);
h264e_init_slice(&ctx->slice);
ctx->sps.pic_width_in_mbs = MB_COUNT(ctx->width);
......@@ -441,6 +480,8 @@ static int h264e_init(struct rk_venc *ictx,
h264e_init_rc(ictx);
/* if level is 31 or greater, we prefer disable 4x4 mv mode
to limit max mv count per 2mb */
if (ctx->sps.level_idc >= H264ENC_LEVEL_3_1)
ctx->h264_inter4x4_disabled = 1;
else
......
......@@ -44,7 +44,6 @@ struct rk_h264_encoder {
char stream_header[H264E_MAX_STREAM_HEADER_SIZE];
int stream_header_size;
int h264_sps_pps_before_idr;
uint8_t h264_profile;
int width;
int height;
......
......@@ -39,7 +39,8 @@ struct rk_vepu_init_param {
union {
struct {
bool h264_sps_pps_before_idr;
uint8_t h264_profile;
uint8_t v4l2_h264_profile;
uint8_t v4l2_h264_level;
} h264e;
};
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment