diff --git a/gst/videotestsrc/gstvideotestsrc.c b/gst/videotestsrc/gstvideotestsrc.c index 5a10a84a48..9d61dbbd3e 100644 --- a/gst/videotestsrc/gstvideotestsrc.c +++ b/gst/videotestsrc/gstvideotestsrc.c @@ -130,6 +130,8 @@ gst_video_test_src_pattern_get_type (void) {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"}, + {GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE, "Chroma zone plate", + "chroma-zone-plate"}, {0, NULL, NULL} }; @@ -358,6 +360,9 @@ gst_video_test_src_set_pattern (GstVideoTestSrc * videotestsrc, case GST_VIDEO_TEST_SRC_GAMUT: videotestsrc->make_image = gst_video_test_src_gamut; break; + case GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE: + videotestsrc->make_image = gst_video_test_src_chromazoneplate; + break; default: g_assert_not_reached (); } diff --git a/gst/videotestsrc/gstvideotestsrc.h b/gst/videotestsrc/gstvideotestsrc.h index 0cc80b203f..814b1d60c1 100644 --- a/gst/videotestsrc/gstvideotestsrc.h +++ b/gst/videotestsrc/gstvideotestsrc.h @@ -55,6 +55,7 @@ G_BEGIN_DECLS * @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 + * @GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE: Chroma zone plate * * The test pattern to produce. * @@ -66,6 +67,14 @@ G_BEGIN_DECLS * 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. + * + * The Zone Plate pattern is based on BBC R&D Report 1978/23, and can + * be used to test spatial frequency response of a system. This + * pattern generator is controlled by the xoffset and yoffset parameters + * and also by all the parameters starting with 'k'. The default + * parameters produce a grey pattern. Try 'videotestsrc + * pattern=zone-plate kx2=20 ky2=20 kt=1' to produce something + * interesting. */ typedef enum { GST_VIDEO_TEST_SRC_SMPTE, @@ -83,7 +92,8 @@ typedef enum { GST_VIDEO_TEST_SRC_BLINK, GST_VIDEO_TEST_SRC_SMPTE75, GST_VIDEO_TEST_SRC_ZONE_PLATE, - GST_VIDEO_TEST_SRC_GAMUT + GST_VIDEO_TEST_SRC_GAMUT, + GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE } GstVideoTestSrcPattern; /** diff --git a/gst/videotestsrc/videotestsrc.c b/gst/videotestsrc/videotestsrc.c index 4a27e0a7fd..f912363d38 100644 --- a/gst/videotestsrc/videotestsrc.c +++ b/gst/videotestsrc/videotestsrc.c @@ -1356,6 +1356,137 @@ gst_video_test_src_zoneplate (GstVideoTestSrc * v, unsigned char *dest, t++; } +void +gst_video_test_src_chromazoneplate (GstVideoTestSrc * v, unsigned char *dest, + int w, int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + struct vts_color_struct_rgb rgb_color; + struct vts_color_struct_yuv yuv_color; + struct vts_color_struct_gray gray_color; + static uint8_t sine_array[256]; + static int sine_array_inited = FALSE; + + static int t = 0; /* time - increment phase vs time by 1 for each generated frame */ + /* this may not fit with the correct gstreamer notion of time, so maybe FIXME? */ + + int xreset = -(w / 2) - v->xoffset; /* starting values for x^2 and y^2, centering the ellipse */ + int yreset = -(h / 2) - v->yoffset; + + int x, y; + int accum_kx; + int accum_kxt; + int accum_ky; + int accum_kyt; + int accum_kxy; + int kt; + int kt2; + int ky2; + int delta_kxt = v->kxt * t; + int delta_kxy; + int scale_kxy = 0xffff / (w / 2); + int scale_kx2 = 0xffff / w; + + if (!sine_array_inited) { + int black = 16; + int white = 235; + int range = white - black; + for (i = 0; i < 256; i++) { + sine_array[i] = + floor (range * (0.5 + 0.5 * sin (i * 2 * M_PI / 256)) + 0.5 + black); + } + sine_array_inited = TRUE; + } + + 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; + + rgb_color = p->rgb_colors[COLOR_BLACK]; + yuv_color = p->yuv_colors[COLOR_BLACK]; + gray_color = p->gray_colors[COLOR_BLACK]; + p->rgb_color = &rgb_color; + p->yuv_color = &yuv_color; + p->gray_color = &gray_color; + + /* Zoneplate equation: + * + * phase = k0 + kx*x + ky*y + kt*t + * + kxt*x*t + kyt*y*t + kxy*x*y + * + kx2*x*x + ky2*y*y + Kt2*t*t + */ + + /* optimised version, with original code shown in comments */ + accum_ky = 0; + accum_kyt = 0; + kt = v->kt * t; + kt2 = v->kt2 * t * t; + for (j = 0, y = yreset; j < h; j++, y++) { + accum_kx = 0; + accum_kxt = 0; + accum_ky += v->ky; + accum_kyt += v->kyt * t; + delta_kxy = v->kxy * y * scale_kxy; + accum_kxy = delta_kxy * xreset; + ky2 = (v->ky2 * y * y) / h; + for (i = 0, x = xreset; i < w; i++, x++) { + + //zero order + int phase = v->k0; + + //first order + accum_kx += v->kx; + //phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); + phase = phase + accum_kx + accum_ky + kt; + + //cross term + accum_kxt += delta_kxt; + accum_kxy += delta_kxy; + //phase = phase + (v->kxt * i * t) + (v->kyt * j * t); + phase = phase + accum_kxt + accum_kyt; + + //phase = phase + (v->kxy * x * y) / (w/2); + //phase = phase + accum_kxy / (w/2) ; + phase = phase + (accum_kxy >> 16); + + /*second order */ + /*normalise x/y terms to rate of change of phase at the picture edge */ + //phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); + phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1); + + yuv_color.Y = 128; + yuv_color.U = sine_array[phase & 0xff]; + yuv_color.V = sine_array[phase & 0xff]; + + rgb_color.R = 128; + rgb_color.G = 128; + rgb_color.B = yuv_color.V; + + gray_color.G = yuv_color.Y << 8; + p->paint_hline (p, i, j, 1); + } + } + + t++; +} + +#undef SCALE_AMPLITUDE #undef SCALE_AMPLITUDE void gst_video_test_src_circular (GstVideoTestSrc * v, unsigned char *dest, diff --git a/gst/videotestsrc/videotestsrc.h b/gst/videotestsrc/videotestsrc.h index f3f823f001..61ba600d8f 100644 --- a/gst/videotestsrc/videotestsrc.h +++ b/gst/videotestsrc/videotestsrc.h @@ -116,6 +116,8 @@ 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); +void gst_video_test_src_chromazoneplate (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); extern struct fourcc_list_struct fourcc_list[]; extern int n_fourccs;