Commit 429175e4 authored by Ricardo Ribalda Delgado's avatar Ricardo Ribalda Delgado Committed by Mauro Carvalho Chehab

[media] vivid: Add support for HSV encoding

Support HSV encoding. Most of the logic is replicated from ycbcr_enc.
Signed-off-by: default avatarRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 5f3d32ec
...@@ -504,6 +504,7 @@ static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b, ...@@ -504,6 +504,7 @@ static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b,
int max_rgb, min_rgb, diff_rgb; int max_rgb, min_rgb, diff_rgb;
int aux; int aux;
int third; int third;
int third_size;
r >>= 4; r >>= 4;
g >>= 4; g >>= 4;
...@@ -530,30 +531,36 @@ static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b, ...@@ -530,30 +531,36 @@ static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b,
return; return;
} }
third_size = (tpg->real_hsv_enc == V4L2_HSV_ENC_180) ? 60 : 85;
/* Hue */ /* Hue */
if (max_rgb == r) { if (max_rgb == r) {
aux = g - b; aux = g - b;
third = 0; third = 0;
} else if (max_rgb == g) { } else if (max_rgb == g) {
aux = b - r; aux = b - r;
third = 60; third = third_size;
} else { } else {
aux = r - g; aux = r - g;
third = 120; third = third_size * 2;
} }
aux *= 30; aux *= third_size / 2;
aux += diff_rgb / 2; aux += diff_rgb / 2;
aux /= diff_rgb; aux /= diff_rgb;
aux += third; aux += third;
/* Clamp Hue */ /* Clamp Hue */
if (aux < 0) if (tpg->real_hsv_enc == V4L2_HSV_ENC_180) {
aux += 180; if (aux < 0)
else if (aux > 180) aux += 180;
aux -= 180; else if (aux > 180)
*h = aux; aux -= 180;
} else {
aux = aux & 0xff;
}
*h = aux;
} }
static void rgb2ycbcr(const int m[3][3], int r, int g, int b, static void rgb2ycbcr(const int m[3][3], int r, int g, int b,
...@@ -1928,6 +1935,7 @@ static void tpg_recalc(struct tpg_data *tpg) ...@@ -1928,6 +1935,7 @@ static void tpg_recalc(struct tpg_data *tpg)
tpg->recalc_lines = true; tpg->recalc_lines = true;
tpg->real_xfer_func = tpg->xfer_func; tpg->real_xfer_func = tpg->xfer_func;
tpg->real_ycbcr_enc = tpg->ycbcr_enc; tpg->real_ycbcr_enc = tpg->ycbcr_enc;
tpg->real_hsv_enc = tpg->hsv_enc;
tpg->real_quantization = tpg->quantization; tpg->real_quantization = tpg->quantization;
if (tpg->xfer_func == V4L2_XFER_FUNC_DEFAULT) if (tpg->xfer_func == V4L2_XFER_FUNC_DEFAULT)
...@@ -2018,6 +2026,7 @@ void tpg_log_status(struct tpg_data *tpg) ...@@ -2018,6 +2026,7 @@ void tpg_log_status(struct tpg_data *tpg)
pr_info("tpg colorspace: %d\n", tpg->colorspace); pr_info("tpg colorspace: %d\n", tpg->colorspace);
pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func); pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func);
pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc); pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc);
pr_info("tpg HSV encoding: %d/%d\n", tpg->hsv_enc, tpg->real_hsv_enc);
pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization); pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range); pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
} }
......
...@@ -346,6 +346,7 @@ struct vivid_dev { ...@@ -346,6 +346,7 @@ struct vivid_dev {
struct v4l2_dv_timings dv_timings_out; struct v4l2_dv_timings dv_timings_out;
u32 colorspace_out; u32 colorspace_out;
u32 ycbcr_enc_out; u32 ycbcr_enc_out;
u32 hsv_enc_out;
u32 quantization_out; u32 quantization_out;
u32 xfer_func_out; u32 xfer_func_out;
u32 service_set_out; u32 service_set_out;
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 40) #define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 40)
#define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 41) #define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 41)
#define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42) #define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42)
#define VIVID_CID_HSV_ENC (VIVID_CID_VIVID_BASE + 43)
#define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60) #define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60)
#define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61) #define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61)
...@@ -378,6 +379,14 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl) ...@@ -378,6 +379,14 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
vivid_send_source_change(dev, HDMI); vivid_send_source_change(dev, HDMI);
vivid_send_source_change(dev, WEBCAM); vivid_send_source_change(dev, WEBCAM);
break; break;
case VIVID_CID_HSV_ENC:
tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
V4L2_HSV_ENC_180);
vivid_send_source_change(dev, TV);
vivid_send_source_change(dev, SVID);
vivid_send_source_change(dev, HDMI);
vivid_send_source_change(dev, WEBCAM);
break;
case VIVID_CID_QUANTIZATION: case VIVID_CID_QUANTIZATION:
tpg_s_quantization(&dev->tpg, ctrl->val); tpg_s_quantization(&dev->tpg, ctrl->val);
vivid_send_source_change(dev, TV); vivid_send_source_change(dev, TV);
...@@ -778,6 +787,21 @@ static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = { ...@@ -778,6 +787,21 @@ static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
.qmenu = vivid_ctrl_ycbcr_enc_strings, .qmenu = vivid_ctrl_ycbcr_enc_strings,
}; };
static const char * const vivid_ctrl_hsv_enc_strings[] = {
"Hue 0-179",
"Hue 0-256",
NULL,
};
static const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
.ops = &vivid_vid_cap_ctrl_ops,
.id = VIVID_CID_HSV_ENC,
.name = "HSV Encoding",
.type = V4L2_CTRL_TYPE_MENU,
.max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
.qmenu = vivid_ctrl_hsv_enc_strings,
};
static const char * const vivid_ctrl_quantization_strings[] = { static const char * const vivid_ctrl_quantization_strings[] = {
"Default", "Default",
"Full Range", "Full Range",
...@@ -1454,6 +1478,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, ...@@ -1454,6 +1478,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
&vivid_ctrl_colorspace, NULL); &vivid_ctrl_colorspace, NULL);
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
} }
......
...@@ -510,6 +510,13 @@ static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev) ...@@ -510,6 +510,13 @@ static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev)
return dev->ycbcr_enc_out; return dev->ycbcr_enc_out;
} }
static unsigned int vivid_hsv_enc_cap(struct vivid_dev *dev)
{
if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
return tpg_g_hsv_enc(&dev->tpg);
return dev->hsv_enc_out;
}
static unsigned vivid_quantization_cap(struct vivid_dev *dev) static unsigned vivid_quantization_cap(struct vivid_dev *dev)
{ {
if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev)) if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
...@@ -530,7 +537,10 @@ int vivid_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -530,7 +537,10 @@ int vivid_g_fmt_vid_cap(struct file *file, void *priv,
mp->pixelformat = dev->fmt_cap->fourcc; mp->pixelformat = dev->fmt_cap->fourcc;
mp->colorspace = vivid_colorspace_cap(dev); mp->colorspace = vivid_colorspace_cap(dev);
mp->xfer_func = vivid_xfer_func_cap(dev); mp->xfer_func = vivid_xfer_func_cap(dev);
mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev); if (dev->fmt_cap->color_enc == TGP_COLOR_ENC_HSV)
mp->hsv_enc = vivid_hsv_enc_cap(dev);
else
mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
mp->quantization = vivid_quantization_cap(dev); mp->quantization = vivid_quantization_cap(dev);
mp->num_planes = dev->fmt_cap->buffers; mp->num_planes = dev->fmt_cap->buffers;
for (p = 0; p < mp->num_planes; p++) { for (p = 0; p < mp->num_planes; p++) {
...@@ -618,7 +628,10 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv, ...@@ -618,7 +628,10 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved)); memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
} }
mp->colorspace = vivid_colorspace_cap(dev); mp->colorspace = vivid_colorspace_cap(dev);
mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev); if (fmt->color_enc == TGP_COLOR_ENC_HSV)
mp->hsv_enc = vivid_hsv_enc_cap(dev);
else
mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
mp->xfer_func = vivid_xfer_func_cap(dev); mp->xfer_func = vivid_xfer_func_cap(dev);
mp->quantization = vivid_quantization_cap(dev); mp->quantization = vivid_quantization_cap(dev);
memset(mp->reserved, 0, sizeof(mp->reserved)); memset(mp->reserved, 0, sizeof(mp->reserved));
......
...@@ -630,6 +630,7 @@ void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt) ...@@ -630,6 +630,7 @@ void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
mp->field = pix->field; mp->field = pix->field;
mp->colorspace = pix->colorspace; mp->colorspace = pix->colorspace;
mp->xfer_func = pix->xfer_func; mp->xfer_func = pix->xfer_func;
/* Also copies hsv_enc */
mp->ycbcr_enc = pix->ycbcr_enc; mp->ycbcr_enc = pix->ycbcr_enc;
mp->quantization = pix->quantization; mp->quantization = pix->quantization;
mp->num_planes = 1; mp->num_planes = 1;
...@@ -659,6 +660,7 @@ int fmt_sp2mp_func(struct file *file, void *priv, ...@@ -659,6 +660,7 @@ int fmt_sp2mp_func(struct file *file, void *priv,
pix->field = mp->field; pix->field = mp->field;
pix->colorspace = mp->colorspace; pix->colorspace = mp->colorspace;
pix->xfer_func = mp->xfer_func; pix->xfer_func = mp->xfer_func;
/* Also copies hsv_enc */
pix->ycbcr_enc = mp->ycbcr_enc; pix->ycbcr_enc = mp->ycbcr_enc;
pix->quantization = mp->quantization; pix->quantization = mp->quantization;
pix->sizeimage = ppix->sizeimage; pix->sizeimage = ppix->sizeimage;
......
...@@ -256,6 +256,7 @@ void vivid_update_format_out(struct vivid_dev *dev) ...@@ -256,6 +256,7 @@ void vivid_update_format_out(struct vivid_dev *dev)
} }
dev->xfer_func_out = V4L2_XFER_FUNC_DEFAULT; dev->xfer_func_out = V4L2_XFER_FUNC_DEFAULT;
dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT; dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT;
dev->hsv_enc_out = V4L2_HSV_ENC_180;
dev->quantization_out = V4L2_QUANTIZATION_DEFAULT; dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
dev->compose_out = dev->sink_rect; dev->compose_out = dev->sink_rect;
dev->compose_bounds_out = dev->sink_rect; dev->compose_bounds_out = dev->sink_rect;
......
...@@ -130,6 +130,7 @@ struct tpg_data { ...@@ -130,6 +130,7 @@ struct tpg_data {
u32 colorspace; u32 colorspace;
u32 xfer_func; u32 xfer_func;
u32 ycbcr_enc; u32 ycbcr_enc;
u32 hsv_enc;
/* /*
* Stores the actual transfer function, i.e. will never be * Stores the actual transfer function, i.e. will never be
* V4L2_XFER_FUNC_DEFAULT. * V4L2_XFER_FUNC_DEFAULT.
...@@ -139,6 +140,7 @@ struct tpg_data { ...@@ -139,6 +140,7 @@ struct tpg_data {
* Stores the actual Y'CbCr encoding, i.e. will never be * Stores the actual Y'CbCr encoding, i.e. will never be
* V4L2_YCBCR_ENC_DEFAULT. * V4L2_YCBCR_ENC_DEFAULT.
*/ */
u32 real_hsv_enc;
u32 real_ycbcr_enc; u32 real_ycbcr_enc;
u32 quantization; u32 quantization;
/* /*
...@@ -341,6 +343,19 @@ static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg) ...@@ -341,6 +343,19 @@ static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg)
return tpg->ycbcr_enc; return tpg->ycbcr_enc;
} }
static inline void tpg_s_hsv_enc(struct tpg_data *tpg, u32 hsv_enc)
{
if (tpg->hsv_enc == hsv_enc)
return;
tpg->hsv_enc = hsv_enc;
tpg->recalc_colors = true;
}
static inline u32 tpg_g_hsv_enc(const struct tpg_data *tpg)
{
return tpg->hsv_enc;
}
static inline void tpg_s_xfer_func(struct tpg_data *tpg, u32 xfer_func) static inline void tpg_s_xfer_func(struct tpg_data *tpg, u32 xfer_func)
{ {
if (tpg->xfer_func == xfer_func) if (tpg->xfer_func == xfer_func)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment