video-chroma: Add support for any combination of chroma-site flags

We've been allowing only a few known chroma-site values such as
jpeg (not co-sited), mpeg2 (horizontally co-sited) and
dv (co-sited on alternate lines). That's insufficient for
representing all possible chroma-site values. By this commit,
we can represent any combination of chroma-site flags.
But, an exception here is that any combination with
GST_VIDEO_CHROMA_SITE_NONE will be considered as invalid value.

For any combination of chroma-site flags,
gst_video_chroma_to_string() method is deprecated in order to
return newly allocated string via a new gst_video_chroma_site_to_string()
method. And for consistent API naming, gst_video_chroma_from_string()
is also deprecated. Newly written code should use
gst_video_chroma_site_from_string() instead.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/927>
This commit is contained in:
Seungha Yang 2020-11-10 18:01:12 +09:00 committed by GStreamer Merge Bot
parent 6434db5298
commit 410efd196a
3 changed files with 193 additions and 5 deletions

View file

@ -26,7 +26,7 @@
#include "video-orc.h"
#include "video-format.h"
#include <gst/video/video-enumtypes.h>
/**
* SECTION:gstvideochroma
@ -72,7 +72,9 @@ typedef struct
static const ChromaSiteInfo chromasite[] = {
{"jpeg", GST_VIDEO_CHROMA_SITE_JPEG},
{"mpeg2", GST_VIDEO_CHROMA_SITE_MPEG2},
{"dv", GST_VIDEO_CHROMA_SITE_DV}
{"dv", GST_VIDEO_CHROMA_SITE_DV},
{"alt-line", GST_VIDEO_CHROMA_SITE_ALT_LINE},
{"cosited", GST_VIDEO_CHROMA_SITE_COSITED},
};
/**
@ -81,18 +83,66 @@ static const ChromaSiteInfo chromasite[] = {
*
* Convert @s to a #GstVideoChromaSite
*
* Deprecated: 1.20: Use gst_video_chroma_site_from_string() instead.
*
* Returns: a #GstVideoChromaSite or %GST_VIDEO_CHROMA_SITE_UNKNOWN when @s does
* not contain a valid chroma description.
*/
GstVideoChromaSite
gst_video_chroma_from_string (const gchar * s)
{
return gst_video_chroma_site_from_string (s);
}
/**
* gst_video_chroma_site_from_string:
* @s: a chromasite string
*
* Convert @s to a #GstVideoChromaSite
*
* Returns: a #GstVideoChromaSite or %GST_VIDEO_CHROMA_SITE_UNKNOWN when @s does
* not contain a valid chroma-site description.
*
* Since: 1.20
*/
GstVideoChromaSite
gst_video_chroma_site_from_string (const gchar * s)
{
gint i;
gchar **split;
gchar **iter;
GstVideoChromaSite ret = GST_VIDEO_CHROMA_SITE_UNKNOWN;
GFlagsClass *klass;
for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
if (g_str_equal (chromasite[i].name, s))
return chromasite[i].site;
}
return GST_VIDEO_CHROMA_SITE_UNKNOWN;
klass = (GFlagsClass *) g_type_class_ref (GST_TYPE_VIDEO_CHROMA_SITE);
split = g_strsplit (s, "+", 0);
for (iter = split; *iter; iter++) {
GFlagsValue *value;
value = g_flags_get_value_by_nick (klass, *iter);
if (!value) {
ret = GST_VIDEO_CHROMA_SITE_UNKNOWN;
goto out;
}
ret |= value->value;
}
out:
g_type_class_unref (klass);
g_strfreev (split);
/* Doesn't make sense */
if ((ret & GST_VIDEO_CHROMA_SITE_NONE) != 0 &&
ret != GST_VIDEO_CHROMA_SITE_NONE)
return GST_VIDEO_CHROMA_SITE_UNKNOWN;
return ret;
}
/**
@ -101,6 +151,8 @@ gst_video_chroma_from_string (const gchar * s)
*
* Converts @site to its string representation.
*
* Deprecated: 1.20: Use gst_video_chroma_site_to_string() instead.
*
* Returns: a string describing @site.
*/
const gchar *
@ -114,6 +166,60 @@ gst_video_chroma_to_string (GstVideoChromaSite site)
return NULL;
}
/**
* gst_video_chroma_site_to_string:
* @site: a #GstVideoChromaSite
*
* Converts @site to its string representation.
*
* Returns: (transfer full) (nullable): a string representation of @site
* or %NULL if @site contains undefined value or
* is equal to %GST_VIDEO_CHROMA_SITE_UNKNOWN
*
* Since: 1.20
*/
gchar *
gst_video_chroma_site_to_string (GstVideoChromaSite site)
{
gint i;
GString *str;
GFlagsValue *value;
GFlagsClass *klass;
/* return null string for GST_VIDEO_CHROMA_SITE_UNKNOWN */
if (site == 0)
return NULL;
for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
if (chromasite[i].site == site)
return g_strdup (chromasite[i].name);
}
/* Doesn't make sense */
if ((site & GST_VIDEO_CHROMA_SITE_NONE) != 0 &&
site != GST_VIDEO_CHROMA_SITE_NONE)
return NULL;
/* Construct new string */
klass = (GFlagsClass *) g_type_class_ref (GST_TYPE_VIDEO_CHROMA_SITE);
str = g_string_new (NULL);
while (site != GST_VIDEO_CHROMA_SITE_UNKNOWN &&
(value = g_flags_get_first_value (klass, site))) {
if (str->len > 0)
g_string_append (str, "+");
g_string_append (str, value->value_nick);
site &= ~value->value;
}
g_type_class_unref (klass);
/* This means given chroma-site has unknown value */
if (site != 0)
return g_string_free (str, TRUE);
return g_string_free (str, FALSE);
}
struct _GstVideoChromaResample
{
GstVideoChromaMethod method;

View file

@ -52,12 +52,18 @@ typedef enum {
GST_VIDEO_CHROMA_SITE_DV = (GST_VIDEO_CHROMA_SITE_COSITED | GST_VIDEO_CHROMA_SITE_ALT_LINE),
} GstVideoChromaSite;
GST_VIDEO_API
GST_VIDEO_DEPRECATED_FOR(gst_video_chroma_site_from_string)
GstVideoChromaSite gst_video_chroma_from_string (const gchar * s);
GST_VIDEO_API
GST_VIDEO_DEPRECATED_FOR(gst_video_chroma_site_to_string)
const gchar * gst_video_chroma_to_string (GstVideoChromaSite site);
GST_VIDEO_API
GstVideoChromaSite gst_video_chroma_site_from_string (const gchar * s);
GST_VIDEO_API
gchar * gst_video_chroma_site_to_string (GstVideoChromaSite site);
/**
* GstVideoChromaMethod:
* @GST_VIDEO_CHROMA_METHOD_NEAREST: Duplicates the chroma samples when

View file

@ -2398,6 +2398,81 @@ GST_END_TEST;
#undef HEIGHT
#undef TIME
typedef struct
{
const gchar *name;
GstVideoChromaSite site;
} ChromaSiteElem;
GST_START_TEST (test_video_chroma_site)
{
ChromaSiteElem valid_sites[] = {
/* pre-defined flags */
{"jpeg", GST_VIDEO_CHROMA_SITE_JPEG},
{"mpeg2", GST_VIDEO_CHROMA_SITE_MPEG2},
{"dv", GST_VIDEO_CHROMA_SITE_DV},
{"alt-line", GST_VIDEO_CHROMA_SITE_ALT_LINE},
{"cosited", GST_VIDEO_CHROMA_SITE_COSITED},
/* new values */
{"v-cosited", GST_VIDEO_CHROMA_SITE_V_COSITED},
{"v-cosited+alt-line",
GST_VIDEO_CHROMA_SITE_V_COSITED | GST_VIDEO_CHROMA_SITE_ALT_LINE},
};
ChromaSiteElem unknown_sites[] = {
{NULL, GST_VIDEO_CHROMA_SITE_UNKNOWN},
/* Any combination with GST_VIDEO_CHROMA_SITE_NONE doesn' make sense */
{NULL, GST_VIDEO_CHROMA_SITE_NONE | GST_VIDEO_CHROMA_SITE_H_COSITED},
};
gint i;
for (i = 0; i < G_N_ELEMENTS (valid_sites); i++) {
gchar *site = gst_video_chroma_site_to_string (valid_sites[i].site);
fail_unless (site != NULL);
fail_unless (g_strcmp0 (site, valid_sites[i].name) == 0);
fail_unless (gst_video_chroma_site_from_string (site) ==
valid_sites[i].site);
g_free (site);
}
for (i = 0; i < G_N_ELEMENTS (unknown_sites); i++) {
gchar *site = gst_video_chroma_site_to_string (unknown_sites[i].site);
fail_unless (site == NULL);
}
/* totally wrong string */
fail_unless (gst_video_chroma_site_from_string ("foo/bar") ==
GST_VIDEO_CHROMA_SITE_UNKNOWN);
/* valid ones */
fail_unless (gst_video_chroma_site_from_string ("jpeg") ==
GST_VIDEO_CHROMA_SITE_NONE);
fail_unless (gst_video_chroma_site_from_string ("none") ==
GST_VIDEO_CHROMA_SITE_NONE);
fail_unless (gst_video_chroma_site_from_string ("mpeg2") ==
GST_VIDEO_CHROMA_SITE_H_COSITED);
fail_unless (gst_video_chroma_site_from_string ("h-cosited") ==
GST_VIDEO_CHROMA_SITE_H_COSITED);
/* Equal to "cosited" */
fail_unless (gst_video_chroma_site_from_string ("v-cosited+h-cosited") ==
GST_VIDEO_CHROMA_SITE_COSITED);
fail_unless (gst_video_chroma_site_from_string ("v-cosited") ==
GST_VIDEO_CHROMA_SITE_V_COSITED);
/* none + something doesn't make sense */
fail_unless (gst_video_chroma_site_from_string ("none+v-cosited") ==
GST_VIDEO_CHROMA_SITE_UNKNOWN);
/* mix of valid and invalid strings */
fail_unless (gst_video_chroma_site_from_string ("mpeg2+foo/bar") ==
GST_VIDEO_CHROMA_SITE_UNKNOWN);
}
GST_END_TEST;
GST_START_TEST (test_video_scaler)
{
GstVideoScaler *scale;
@ -3959,6 +4034,7 @@ video_suite (void)
tcase_add_test (tc_chain, test_overlay_composition_global_alpha);
tcase_add_test (tc_chain, test_video_pack_unpack2);
tcase_add_test (tc_chain, test_video_chroma);
tcase_add_test (tc_chain, test_video_chroma_site);
tcase_add_test (tc_chain, test_video_scaler);
tcase_add_test (tc_chain, test_video_color_convert_rgb_rgb);
tcase_add_test (tc_chain, test_video_color_convert_rgb_yuv);