tests: make pack/unpack test

Make a more complete pack/unpack test, check if the image after
pack/unpack has the same color and precision, and has correctly
duplicated subsampled pixels.
This commit is contained in:
Wim Taymans 2014-11-06 10:43:11 +01:00
parent 4ab5a29e46
commit 64c1303dd0

View file

@ -1697,6 +1697,207 @@ GST_START_TEST (test_overlay_composition_global_alpha)
GST_END_TEST;
static guint8 *
make_pixels (gint depth, gint width, gint height)
{
guint32 color = 0xff000000;
gint i, j;
if (depth == 8) {
guint8 *pixels = g_malloc (width * height * 4);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
pixels[(i * width + j) * 4 + 0] = ((color >> 24) & 0xff);
pixels[(i * width + j) * 4 + 1] = ((color >> 16) & 0xff);
pixels[(i * width + j) * 4 + 2] = ((color >> 8) & 0xff);
pixels[(i * width + j) * 4 + 3] = (color & 0xff);
color++;
}
}
return pixels;
} else {
#define TO16(a) (((a)<<8)|(a))
guint16 *pixels = g_malloc (width * height * 8);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
pixels[(i * width + j) * 4 + 0] = TO16 ((color >> 24) & 0xff);
pixels[(i * width + j) * 4 + 1] = TO16 ((color >> 16) & 0xff);
pixels[(i * width + j) * 4 + 2] = TO16 ((color >> 8) & 0xff);
pixels[(i * width + j) * 4 + 3] = TO16 (color & 0xff);
color++;
}
}
#undef TO16
return (guint8 *) pixels;
}
}
#define HS(x,o) ((x)&hs[o])
#define WS(x,o) ((x)&ws[o])
#define IN(i,j,o) (in[(HS(i, o)*width + WS(j,o))*4+(o)] & mask[o])
#define OUT(i,j,o) (out[((i)*width + (j))*4+o] & mask[o])
static gint
compare_frame (const GstVideoFormatInfo * finfo, gint depth, guint8 * outpixels,
guint8 * pixels, gint width, gint height)
{
gint diff, i, j, k;
guint ws[4], hs[4], mask[4];
for (k = 0; k < 4; k++) {
hs[k] = G_MAXUINT << finfo->h_sub[(3 + k) % 4];
ws[k] = G_MAXUINT << finfo->w_sub[(3 + k) % 4];
mask[k] = G_MAXUINT << (depth - finfo->depth[(3 + k) % 4]);
}
diff = 0;
if (depth == 8) {
guint8 *in = pixels;
guint8 *out = outpixels;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
for (k = 0; k < 4; k++) {
diff += IN (i, j, k) != OUT (i, j, k);
}
}
}
} else {
guint16 *in = (guint16 *) pixels;
guint16 *out = (guint16 *) outpixels;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
for (k = 0; k < 4; k++) {
diff += IN (i, j, k) != OUT (i, j, k);
}
}
}
}
return diff;
}
#undef WS
#undef HS
#undef IN
#undef OUT
#define UNPACK_FRAME(frame,dest,line,x,width) \
(frame)->info.finfo->unpack_func ((frame)->info.finfo, \
(GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
GST_VIDEO_PACK_FLAG_INTERLACED : \
GST_VIDEO_PACK_FLAG_NONE), \
dest, (frame)->data, (frame)->info.stride, x, \
line, width)
#define PACK_FRAME(frame,src,line,width) \
(frame)->info.finfo->pack_func ((frame)->info.finfo, \
(GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
GST_VIDEO_PACK_FLAG_INTERLACED : \
GST_VIDEO_PACK_FLAG_NONE), \
src, 0, (frame)->data, (frame)->info.stride, \
(frame)->info.chroma_site, line, width);
GST_START_TEST (test_video_pack_unpack2)
{
GstVideoFormat format;
GTimer *timer;
gint num_formats;
#define WIDTH 1920
#define HEIGHT 1080
/* set to something larger to do benchmarks */
#define TIME 0.0
timer = g_timer_new ();
num_formats = get_num_formats ();
GST_DEBUG ("pack/sec\t unpack/sec \tpack GB/sec\tunpack GB/sec\tformat");
for (format = GST_VIDEO_FORMAT_I420; format < num_formats; format++) {
GstVideoInfo info;
const GstVideoFormatInfo *finfo, *fuinfo;
GstBuffer *buffer;
GstVideoFrame frame;
gint k, stride, count, diff, depth;
guint8 *pixels, *outpixels;
gdouble elapsed;
gdouble unpack_sec, pack_sec;
finfo = gst_video_format_get_info (format);
fail_unless (finfo != NULL);
if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo))
continue;
fuinfo = gst_video_format_get_info (finfo->unpack_format);
fail_unless (fuinfo != NULL);
depth = GST_VIDEO_FORMAT_INFO_BITS (fuinfo);
fail_unless (depth == 8 || depth == 16);
pixels = make_pixels (depth, WIDTH, HEIGHT);
stride = WIDTH * (depth >> 1);
gst_video_info_set_format (&info, format, WIDTH, HEIGHT);
buffer = gst_buffer_new_and_alloc (info.size);
gst_video_frame_map (&frame, &info, buffer, GST_MAP_READWRITE);
/* pack the frame into the target format */
/* warmup */
PACK_FRAME (&frame, pixels, 0, WIDTH);
count = 0;
g_timer_start (timer);
while (TRUE) {
for (k = 0; k < HEIGHT; k += finfo->pack_lines) {
PACK_FRAME (&frame, pixels + k * stride, k, WIDTH);
}
count++;
elapsed = g_timer_elapsed (timer, NULL);
if (elapsed >= TIME)
break;
}
unpack_sec = count / elapsed;
outpixels = g_malloc0 (HEIGHT * stride);
/* unpack the frame */
/* warmup */
UNPACK_FRAME (&frame, outpixels, 0, 0, WIDTH);
count = 0;
g_timer_start (timer);
while (TRUE) {
for (k = 0; k < HEIGHT; k += finfo->pack_lines) {
UNPACK_FRAME (&frame, outpixels + k * stride, k, 0, WIDTH);
}
count++;
elapsed = g_timer_elapsed (timer, NULL);
if (elapsed >= TIME)
break;
}
pack_sec = count / elapsed;
/* compare the frame */
diff = compare_frame (finfo, depth, outpixels, pixels, WIDTH, HEIGHT);
GST_DEBUG ("%f \t %f \t %f \t %f \t %s", pack_sec, unpack_sec,
info.size * pack_sec, info.size * unpack_sec, finfo->name);
if (diff != 0) {
gst_util_dump_mem (outpixels, 128);
gst_util_dump_mem (pixels, 128);
fail_if (diff != 0);
}
gst_video_frame_unmap (&frame);
gst_buffer_unref (buffer);
g_free (pixels);
g_free (outpixels);
}
g_timer_destroy (timer);
}
GST_END_TEST;
GST_START_TEST (test_video_scaler)
{
GstVideoScaler *scale;
@ -1708,7 +1909,6 @@ GST_START_TEST (test_video_scaler)
scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_LINEAR,
GST_VIDEO_SCALER_FLAG_NONE, 2, 15, 5, NULL);
gst_video_scaler_free (scale);
}
GST_END_TEST;
@ -1734,6 +1934,7 @@ video_suite (void)
tcase_add_test (tc_chain, test_overlay_composition);
tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
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_scaler);
return s;