diff --git a/gst/videotestsrc/gstvideotestsrc.c b/gst/videotestsrc/gstvideotestsrc.c index 9942cbd1e7..03c55f275c 100644 --- a/gst/videotestsrc/gstvideotestsrc.c +++ b/gst/videotestsrc/gstvideotestsrc.c @@ -129,6 +129,7 @@ gst_video_test_src_pattern_get_type (void) {GST_VIDEO_TEST_SRC_BLINK, "Blink", "blink"}, {GST_VIDEO_TEST_SRC_SMPTE75, "SMPTE 75% color bars", "smpte75"}, {GST_VIDEO_TEST_SRC_ZONE_PLATE, "Zone plate", "zone-plate"}, + {GST_VIDEO_TEST_SRC_GAMUT, "Gamut checkers", "gamut"}, {0, NULL, NULL} }; @@ -354,6 +355,9 @@ gst_video_test_src_set_pattern (GstVideoTestSrc * videotestsrc, case GST_VIDEO_TEST_SRC_ZONE_PLATE: videotestsrc->make_image = gst_video_test_src_zoneplate; break; + case GST_VIDEO_TEST_SRC_GAMUT: + videotestsrc->make_image = gst_video_test_src_gamut; + break; default: g_assert_not_reached (); } diff --git a/gst/videotestsrc/gstvideotestsrc.h b/gst/videotestsrc/gstvideotestsrc.h index 0f9706b0e3..0cc80b203f 100644 --- a/gst/videotestsrc/gstvideotestsrc.h +++ b/gst/videotestsrc/gstvideotestsrc.h @@ -54,8 +54,18 @@ G_BEGIN_DECLS * @GST_VIDEO_TEST_SRC_BLINK: Alternate between black and white * @GST_VIDEO_TEST_SRC_SMPTE75: SMPTE test pattern (75% color bars) * @GST_VIDEO_TEST_SRC_ZONE_PLATE: Zone plate + * @GST_VIDEO_TEST_SRC_GAMUT: Gamut checking pattern * * The test pattern to produce. + * + * The Gamut pattern creates a checkerboard pattern of colors at the + * edge of the YCbCr gamut and nearby colors that are out of gamut. + * The pattern is divided into 4 regions: black, white, red, and blue. + * After conversion to RGB, the out-of-gamut colors should be converted + * to the same value as their in-gamut neighbors. If the checkerboard + * pattern is still visible after conversion, this indicates a faulty + * conversion. Image manipulation, such as adjusting contrast or + * brightness, can also cause the pattern to be visible. */ typedef enum { GST_VIDEO_TEST_SRC_SMPTE, @@ -72,13 +82,14 @@ typedef enum { GST_VIDEO_TEST_SRC_CIRCULAR, GST_VIDEO_TEST_SRC_BLINK, GST_VIDEO_TEST_SRC_SMPTE75, - GST_VIDEO_TEST_SRC_ZONE_PLATE + GST_VIDEO_TEST_SRC_ZONE_PLATE, + GST_VIDEO_TEST_SRC_GAMUT } GstVideoTestSrcPattern; /** * GstVideoTestSrcColorSpec: - * @GST_VIDEO_TEST_SRC_BT601: ITU-R Rec. BT.601 - * @GST_VIDEO_TEST_SRC_BT709: ITU-R Rec. BT.601 + * @GST_VIDEO_TEST_SRC_BT601: ITU-R Rec. BT.601/BT.470 (SD) + * @GST_VIDEO_TEST_SRC_BT709: ITU-R Rec. BT.709 (HD) * * The color specification to use. */ diff --git a/gst/videotestsrc/videotestsrc.c b/gst/videotestsrc/videotestsrc.c index 541aca916b..2969912b04 100644 --- a/gst/videotestsrc/videotestsrc.c +++ b/gst/videotestsrc/videotestsrc.c @@ -1431,6 +1431,95 @@ gst_video_test_src_circular (GstVideoTestSrc * v, unsigned char *dest, } } +void +gst_video_test_src_gamut (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + int x, y; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + struct vts_color_struct_yuv yuv_primary; + struct vts_color_struct_yuv yuv_secondary; + struct vts_color_struct_rgb rgb_primary = { 0 }; + struct vts_color_struct_rgb rgb_secondary = { 0 }; + struct vts_color_struct_gray gray_primary = { 0 }; + struct vts_color_struct_gray gray_secondary = { 0 }; + + p->rgb_colors = vts_colors_rgb; + if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) { + p->yuv_colors = vts_colors_bt601_ycbcr_100; + } else { + p->yuv_colors = vts_colors_bt709_ycbcr_100; + } + p->gray_colors = vts_colors_gray_100; + p->width = w; + p->height = h; + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + p->paint_hline = fourcc->paint_hline; + + for (y = 0; y < h; y++) { + int region = (y * 4) / h; + + switch (region) { + case 0: /* black */ + yuv_primary = p->yuv_colors[COLOR_BLACK]; + yuv_secondary = p->yuv_colors[COLOR_BLACK]; + yuv_secondary.Y = 0; + rgb_primary = p->rgb_colors[COLOR_BLACK]; + rgb_secondary = p->rgb_colors[COLOR_BLACK]; + gray_primary = p->gray_colors[COLOR_BLACK]; + gray_secondary = p->gray_colors[COLOR_BLACK]; + break; + case 1: + yuv_primary = p->yuv_colors[COLOR_WHITE]; + yuv_secondary = p->yuv_colors[COLOR_WHITE]; + yuv_secondary.Y = 255; + rgb_primary = p->rgb_colors[COLOR_WHITE]; + rgb_secondary = p->rgb_colors[COLOR_WHITE]; + gray_primary = p->gray_colors[COLOR_WHITE]; + gray_secondary = p->gray_colors[COLOR_WHITE]; + break; + case 2: + yuv_primary = p->yuv_colors[COLOR_RED]; + yuv_secondary = p->yuv_colors[COLOR_RED]; + yuv_secondary.V = 255; + rgb_primary = p->rgb_colors[COLOR_RED]; + rgb_secondary = p->rgb_colors[COLOR_RED]; + gray_primary = p->gray_colors[COLOR_RED]; + gray_secondary = p->gray_colors[COLOR_RED]; + break; + case 3: + yuv_primary = p->yuv_colors[COLOR_BLUE]; + yuv_secondary = p->yuv_colors[COLOR_BLUE]; + yuv_secondary.U = 255; + rgb_primary = p->rgb_colors[COLOR_BLUE]; + rgb_secondary = p->rgb_colors[COLOR_BLUE]; + gray_primary = p->gray_colors[COLOR_BLUE]; + gray_secondary = p->gray_colors[COLOR_BLUE]; + break; + } + + for (x = 0; x < w; x += 8) { + int len = MIN (8, w - x); + + if ((x ^ y) & (1 << 4)) { + p->rgb_color = &rgb_primary; + p->yuv_color = &yuv_primary; + p->gray_color = &gray_primary; + } else { + p->rgb_color = &rgb_secondary; + p->yuv_color = &yuv_secondary; + p->gray_color = &gray_secondary; + } + p->paint_hline (p, x, y, len); + } + } +} + static void paint_setup_I420 (paintinfo * p, unsigned char *dest) { diff --git a/gst/videotestsrc/videotestsrc.h b/gst/videotestsrc/videotestsrc.h index 58808333c6..f3f823f001 100644 --- a/gst/videotestsrc/videotestsrc.h +++ b/gst/videotestsrc/videotestsrc.h @@ -114,6 +114,8 @@ void gst_video_test_src_circular (GstVideoTestSrc * v, unsigned char *dest, int w, int h); void gst_video_test_src_zoneplate (GstVideoTestSrc * v, unsigned char *dest, int w, int h); +void gst_video_test_src_gamut (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); extern struct fourcc_list_struct fourcc_list[]; extern int n_fourccs;