libv4lplugins: Enable h264 encoder to produce Baseline profile stream

H264 encoder in libv4lplugins hard-coded values in SPS and PPS
specifically for Main profile. Although the hardware on
rockchip is capable of encoding Baseline, Main and High
profile, RK3399 cannot encode Baseline profile stream due to
the plugin code.

This removes some hard-coded values and instead respect the
profile by S_EXT_CTRL with id=V4L2_CID_MPEG_VIDEO_H264_PROFILE.

BUG=chromium:1036219, chromium:1036220
TEST=webrtc.RTCPeerConnectionAccelUsed.enc_h264 on kevin

Change-Id: Ifbdb02fbd82bc9c530c10bff38b8f8933d31376d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/libv4lplugins/+/1977992
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
Tested-by: Hirokazu Honda <hiroh@chromium.org>
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
diff --git a/libv4l-rockchip_v2/libv4l-encplugin-rockchip.c b/libv4l-rockchip_v2/libv4l-encplugin-rockchip.c
index 7081c20..3bf90ac 100644
--- a/libv4l-rockchip_v2/libv4l-encplugin-rockchip.c
+++ b/libv4l-rockchip_v2/libv4l-encplugin-rockchip.c
@@ -197,6 +197,9 @@
 static void get_log_level();
 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);
+
 static void *plugin_init(int fd)
 {
 	int ret;
@@ -501,6 +504,13 @@
 		case V4L2_CID_MPEG_VIDEO_H264_SPS_PPS_BEFORE_IDR:
 			ctx->init_param.h264e.h264_sps_pps_before_idr =
 				ext_ctrls->controls[i].value;
+			break;
+		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 =
+				ext_ctrls->controls[i].value;
+			break;
 		default:
 			break;
 		}
@@ -651,14 +661,15 @@
 
 	if (argp->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
 		/*
-		 * Return invalid unless the queried h264 profile is Main. The
-		 * hardware supports H264 Base, Main, High profile, but this
-		 * plugin supports Main profile only because Main profile is
-		 * hard-coded in h264e_init_sps().
+		 * Filter out other H264 profiles than Baseline and Main
+		 * profile. The hardware supports H264 Baseline, Main, High
+		 * profile, but this plugin supports Baseline and Main profile
+		 * only.
 		 */
-		if (argp->index == V4L2_MPEG_VIDEO_H264_PROFILE_MAIN)
-			return 0;
-		return -EINVAL;
+		if (!is_supported_h264_profile(argp->index)) {
+			return -EINVAL;
+		}
+		return 0;
 	}
 	return SYS_IOCTL(fd, VIDIOC_QUERYMENU, argp);
 }
@@ -668,13 +679,14 @@
 {
 	if (argp->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
 		/*
-		 * Filter out other H264 profiles than Main profile. The
-		 * hardware supports H264 Base, Main, High profile, but this
-		 * plugin supports Main profile only because Main profile is
-		 * hard-coded in h264e_init_sps().
+		 * Filter out other H264 profiles than Baseline and Main
+		 * profile. The hardware supports H264 Baseline, Main, High
+		 * profile, but this plugin supports Baseline and Main profile
+		 * only.
 		 */
 		argp->type = V4L2_CTRL_TYPE_MENU;
-		argp->minimum = argp->maximum = argp->default_value =
+		argp->minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
+		argp->maximum = argp->default_value =
 			V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
 		argp->step = 1;
 		return 0;
@@ -921,6 +933,12 @@
 	}
 }
 
+static bool is_supported_h264_profile(uint8_t profile) {
+	return profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE ||
+		profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE ||
+		profile == V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
+}
+
 PLUGIN_PUBLIC const struct libv4l_dev_ops libv4l2_plugin = {
 	.init = &plugin_init,
 	.close = &plugin_close,
diff --git a/libv4l-rockchip_v2/libvepu/h264e/h264e.c b/libv4l-rockchip_v2/libvepu/h264e/h264e.c
index 48047de..0362089 100644
--- a/libv4l-rockchip_v2/libvepu/h264e/h264e.c
+++ b/libv4l-rockchip_v2/libvepu/h264e/h264e.c
@@ -30,9 +30,21 @@
 	{ 27, 44, 72, 119, 192, 314, 453, 653, 952, 1395, 0x7FFFFFFF },
 	{ 51, 47, 43, 39, 35, 31, 27, 23, 19, 15, 11} };
 
-static void h264e_init_sps(struct v4l2_plugin_h264_sps *sps)
+const int baseline_idc = 66;
+const int main_idc = 77;
+
+static void h264e_init_sps(struct v4l2_plugin_h264_sps *sps, uint8_t profile)
 {
-	sps->profile_idc = 77;
+	switch(profile) {
+	case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+	case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+		sps->profile_idc = baseline_idc;
+		break;
+	case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+	default:
+		sps->profile_idc = main_idc;
+		break;
+	}
 
 	/* fixed values limited by hardware */
 	sps->constraint_set0_flag = 1;
@@ -67,13 +79,16 @@
 	sps->vui_parameters_present_flag = 1;
 }
 
-static void h264e_init_pps(struct v4l2_plugin_h264_pps *pps)
+static void h264e_init_pps(struct v4l2_plugin_h264_pps *pps, uint8_t profile)
 {
 	pps->pic_parameter_set_id = 0;
 	pps->seq_parameter_set_id = 0;
 
-	/* enable cabac coding need set profile_idc large than 77 */
-	pps->entropy_coding_mode_flag = 1;
+	pps->entropy_coding_mode_flag = 0;
+	if (profile >= V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) {
+		/* enable cabac coding need set profile_idc large than 77 */
+		pps->entropy_coding_mode_flag = 1;
+	}
 
 	/* fixed value limited by hardware */
 	pps->pic_order_present_flag = 0;
@@ -334,6 +349,7 @@
 		stream_write_se(pps, ctx->pps.chroma_qp_index_offset,
 				"chroma_qp_index_offset");
 	}
+
 	stream_put_bits(pps, 1, 1, "rbsp_stop_one_bit");
 
 	stream_buffer_flush(pps);
@@ -396,17 +412,18 @@
 
 	ictx->fmt = ENC_FORMAT_H264;
 
-	h264e_init_sps(&ctx->sps);
-	h264e_init_pps(&ctx->pps);
-	h264e_init_slice(&ctx->slice);
-
 	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_slice(&ctx->slice);
+
 	ctx->sps.pic_width_in_mbs = MB_COUNT(ctx->width);
 	ctx->sps.pic_height_in_map_units = MB_COUNT(ctx->height);
 
@@ -650,4 +667,3 @@
 
 	return enc;
 }
-
diff --git a/libv4l-rockchip_v2/libvepu/h264e/h264e.h b/libv4l-rockchip_v2/libvepu/h264e/h264e.h
index 32b8bf7..c944527 100644
--- a/libv4l-rockchip_v2/libvepu/h264e/h264e.h
+++ b/libv4l-rockchip_v2/libvepu/h264e/h264e.h
@@ -44,6 +44,7 @@
 	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;
diff --git a/libv4l-rockchip_v2/libvepu/rk_vepu_interface.h b/libv4l-rockchip_v2/libvepu/rk_vepu_interface.h
index 1e84ddc..78457fe 100644
--- a/libv4l-rockchip_v2/libvepu/rk_vepu_interface.h
+++ b/libv4l-rockchip_v2/libvepu/rk_vepu_interface.h
@@ -39,6 +39,7 @@
 	union {
 		struct {
 			bool h264_sps_pps_before_idr;
+			uint8_t h264_profile;
 		} h264e;
 	};
 };
@@ -121,4 +122,3 @@
 int rk_vepu_assemble_bitstream(void *enc, int fd, struct v4l2_buffer *buffer);
 
 #endif  // LIBVPU_RK_VEPU_INTERFACE_H_
-