[PATCH v2 4/8] qedit/tests: Add tests for GetBitmapBits.

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Oct 23 10:18:54 CDT 2020


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/qedit/tests/mediadet.c | 220 +++++++++++++++++++++++++++++++++++-
 1 file changed, 218 insertions(+), 2 deletions(-)

diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c
index 18a4412..8c5ef4b 100644
--- a/dlls/qedit/tests/mediadet.c
+++ b/dlls/qedit/tests/mediadet.c
@@ -170,7 +170,9 @@ static DWORD WINAPI testfilter_frame_thread(void *arg)
     struct testfilter *filter = arg;
     IMemAllocator *allocator;
     IMediaSample *sample;
+    unsigned i;
     HRESULT hr;
+    DWORD fill;
     BYTE *data;
 
     hr = IMemInputPin_GetAllocator(filter->source.pMemInputPin, &allocator);
@@ -190,7 +192,13 @@ static DWORD WINAPI testfilter_frame_thread(void *arg)
         hr = IMediaSample_GetPointer(sample, &data);
         ok(hr == S_OK, "Got hr %#x.\n", hr);
 
-        memset(data, 0, 640 * 480 * 3);
+        fill = (start_time / 10000 & 0xffffff) ^ 0xccaabb;
+        for (i = 0; i < 640 * 480 * 3; i += 3)
+        {
+            data[i] = fill ^ i;
+            data[i + 1] = fill >> 8 ^ i;
+            data[i + 2] = fill >> 16 ^ i;
+        }
 
         hr = IMediaSample_SetActualDataLength(sample, 640 * 480 * 3);
         ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -609,6 +617,157 @@ static BOOL unpack_avi_file(int id, WCHAR name[MAX_PATH])
     return ret && written == size;
 }
 
+static void stretch_line(BYTE *dst, ULONG dst_width, BYTE *src, ULONG src_width)
+{
+    ULONG ratio, rem, drift, i = dst_width;
+
+    if (dst_width < src_width)
+    {
+        ratio = src_width / dst_width;
+        rem   = src_width % dst_width;
+        drift = 0;
+        while (i--)
+        {
+            dst[0] = src[0];
+            dst[1] = src[1];
+            dst[2] = src[2];
+            dst += 3;
+            src += ratio * 3;
+            if (drift < rem)
+            {
+                src += 3;
+                drift += dst_width;
+            }
+            drift -= rem;
+        }
+    }
+    else if (dst_width > src_width)
+    {
+        drift = dst_width - 1;
+        while (i--)
+        {
+            dst[0] = src[0];
+            dst[1] = src[1];
+            dst[2] = src[2];
+            dst += 3;
+            if (drift < src_width)
+            {
+                drift += dst_width;
+                src += 3;
+            }
+            drift -= src_width;
+        }
+    }
+    else
+    {
+        memcpy(dst, src, dst_width * 3);
+        dst += dst_width * 3;
+    }
+
+    /* Fill the stride padding with zeros */
+    i = (dst_width * 3) % 4;
+    if (i)
+        for (i = 4 - i; i--;)
+            *dst++ = 0;
+}
+
+static void stretch_to_bitmap(BYTE *dst, ULONG dst_width, ULONG dst_height, BYTE *src, ULONG src_width, ULONG src_height)
+{
+    ULONG dst_stride = (dst_width * 3 + 3) & ~3;
+    ULONG src_stride = (src_width * 3 + 3) & ~3;
+    ULONG ratio, rem, drift, i = dst_height;
+    BYTE *dup;
+
+    if (dst_height < src_height)
+    {
+        ratio = src_height / dst_height;
+        rem   = src_height % dst_height;
+        drift = 0;
+        while (i--)
+        {
+            stretch_line(dst, dst_width, src, src_width);
+            dst += dst_stride;
+            src += ratio * src_stride;
+            if (drift < rem)
+            {
+                src += src_stride;
+                drift += dst_height;
+            }
+            drift -= rem;
+        }
+    }
+    else
+    {
+        drift = dst_height - 1;
+        while (i--)
+        {
+            stretch_line(dst, dst_width, src, src_width);
+            dup = dst;
+            dst += dst_stride;
+            while (drift >= src_height && i--)
+            {
+                memcpy(dst, dup, dst_stride);
+                dst += dst_stride;
+                drift -= src_height;
+            }
+            drift += dst_height - src_height;
+            src += src_stride;
+        }
+    }
+}
+
+#define check_bitmap(buffer, width, height, seek_time) check_bitmap_(__LINE__, buffer, width, height, seek_time)
+static void check_bitmap_(unsigned line, void *buffer, LONG width, LONG height, double seek_time)
+{
+    DWORD fill = (DWORD)(seek_time * 1000.0) ^ 0xccaabb;
+    BYTE *p = (BYTE*)buffer + sizeof(BITMAPINFOHEADER);
+    DWORD line_width = (width * 3 + 3) & ~3;
+    BYTE *img, *src = malloc(640 * 480 * 3);
+    const BITMAPINFOHEADER *h = buffer;
+    unsigned i, j, v;
+
+    ok_(__FILE__,line)(h->biSize == sizeof(BITMAPINFOHEADER), "Got biSize %u.\n", h->biSize);
+    ok_(__FILE__,line)(h->biWidth == width, "Got biWidth %d.\n", h->biWidth);
+    ok_(__FILE__,line)(h->biHeight == height, "Got biHeight %d.\n", h->biHeight);
+    ok_(__FILE__,line)(h->biPlanes == 1, "Got biPlanes %d.\n", h->biPlanes);
+    ok_(__FILE__,line)(h->biBitCount == 24, "Got biBitCount %d.\n", h->biBitCount);
+    ok_(__FILE__,line)(h->biCompression == BI_RGB, "Got biCompression %d.\n", h->biCompression);
+    ok_(__FILE__,line)(h->biXPelsPerMeter == 0, "Got biXPelsPerMeter %d.\n", h->biXPelsPerMeter);
+    ok_(__FILE__,line)(h->biYPelsPerMeter == 0, "Got biYPelsPerMeter %d.\n", h->biYPelsPerMeter);
+    ok_(__FILE__,line)(h->biClrUsed == 0, "Got biClrUsed %d.\n", h->biClrUsed);
+    ok_(__FILE__,line)(h->biClrImportant == 0, "Got biClrImportant %d.\n", h->biClrImportant);
+
+    /* The lines are reversed since our source was top-down */
+    src = malloc(640 * 480 * 3);
+    img = src;
+    for (j = 640 * 480 * 3; j != 0;)
+    {
+        j -= 640 * 3;
+        v = j;
+        for (i = 0; i < 640 * 3; i += 3, v += 3)
+        {
+            img[i] = fill ^ v;
+            img[i + 1] = fill >> 8 ^ v;
+            img[i + 2] = fill >> 16 ^ v;
+        }
+        img += 640 * 3;
+    }
+
+    img = malloc(line_width * height);
+    stretch_to_bitmap(img, width, height, src, 640, 480);
+    free(src);
+
+    for (i = 0; i < line_width * height; i += 3)
+        if (p[i] != img[i] || p[i + 1] != img[i + 1] || p[i + 2] != img[i + 2])
+        {
+            ok_(__FILE__,line)(0, "Wrong bitmap data at offset %u (got 0x%06x, expected 0x%06x).\n",
+                               p + i - (BYTE*)buffer, p[i] | p[i + 1] << 8 | p[i + 2] << 16,
+                               img[i] | img[i + 1] << 8 | img[i + 2] << 16);
+            break;
+        }
+    free(img);
+}
+
 static BOOL init_tests(void)
 {
     return unpack_avi_file(TEST_AVI_RES, test_avi_filename)
@@ -1300,7 +1459,7 @@ static void test_bitmap_grab_mode(void)
         &TIME_FORMAT_BYTE,
         &TIME_FORMAT_MEDIA_TIME
     };
-    char *buf = malloc(640 * 480 * 3);
+    char *buf = malloc(sizeof(BITMAPINFOHEADER) + 960 * 720 * 3);
     struct testfilter testfilter;
     FILTER_INFO filter_info;
     IReferenceClock *clock;
@@ -1327,6 +1486,9 @@ static void test_bitmap_grab_mode(void)
 
     hr = IMediaDet_EnterBitmapGrabMode(detector, 0.0);
     ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+    size = sizeof(BITMAPINFOHEADER) + 640 * 480 * 3;
+    hr = IMediaDet_GetBitmapBits(detector, 0.0, &size, buf, 640, 480);
+    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
     hr = IMediaDet_GetSampleGrabber(detector, &sg);
     ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
 
@@ -1493,6 +1655,42 @@ static void test_bitmap_grab_mode(void)
     ok(clock == NULL, "Got non-NULL clock.\n");
     IMediaFilter_Release(mf);
 
+    /* Despite what MSDN states, size must be properly supplied on newer Windows versions */
+    hr = IMediaDet_GetBitmapBits(detector, 0.0, NULL, NULL, 640, 480);
+    todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+    size = -1;
+    hr = IMediaDet_GetBitmapBits(detector, 0.0, &size, buf, 640, 480);
+    todo_wine ok(hr == E_INVALIDARG || broken(hr == S_OK) /* WinXP */, "Got hr %#x.\n", hr);
+    size = 640 * 480 * 3;
+    hr = IMediaDet_GetBitmapBits(detector, 0.0, &size, buf, 640, 480);
+    todo_wine ok(hr == E_OUTOFMEMORY || broken(hr == S_OK) /* WinXP */, "Got hr %#x.\n", hr);
+    ok(size == 640 * 480 * 3, "Got size %d.\n", size);
+    size = sizeof(BITMAPINFOHEADER) + 640 * 480 * 3;
+    hr = IMediaDet_GetBitmapBits(detector, -1.0, &size, buf, 640, 480);
+    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+    hr = IMediaDet_GetBitmapBits(detector, 2.5, &size, buf, 640, 480);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine check_bitmap(buf, 640, 480, 2.5);
+
+    /* GetBitmapBits/WriteBitmapBits can scale the image */
+    size = sizeof(BITMAPINFOHEADER) + 960 * 720 * 3;
+    hr = IMediaDet_GetBitmapBits(detector, 1.5, &size, buf, 131, 151);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(size == sizeof(BITMAPINFOHEADER) + 960 * 720 * 3, "Got size %d.\n", size);
+    todo_wine check_bitmap(buf, 131, 151, 1.5);
+    hr = IMediaDet_GetBitmapBits(detector, 4.0, NULL, buf, 503, 79);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine check_bitmap(buf, 503, 79, 4.0);
+    hr = IMediaDet_GetBitmapBits(detector, 1.52, NULL, buf, 139, 487);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine check_bitmap(buf, 139, 487, 1.52);
+    hr = IMediaDet_GetBitmapBits(detector, 2.12, NULL, buf, 640, 641);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine check_bitmap(buf, 640, 641, 2.12);
+    hr = IMediaDet_GetBitmapBits(detector, 3.25, NULL, buf, 960, 720);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine check_bitmap(buf, 960, 720, 3.25);
+
     /* Changing filter resets bitmap grab mode */
     testfilter.bitmap_grab_mode = FALSE;
     hr = IMediaDet_put_Filter(detector, &testfilter.filter.IUnknown_inner);
@@ -1503,6 +1701,24 @@ static void test_bitmap_grab_mode(void)
     ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(count == 1, "Got %d streams.\n", count);
 
+    /* GetBitmapBits enables it only if it retrieves the image */
+    testfilter.bitmap_grab_mode = TRUE;
+    hr = IMediaDet_GetBitmapBits(detector, 1.25, &size, NULL, 640, 480);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IMediaDet_GetSampleGrabber(detector, &sg);
+    ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
+    hr = IMediaDet_get_OutputStreams(detector, &count);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(count == 1, "Got %d streams.\n", count);
+
+    hr = IMediaDet_GetBitmapBits(detector, 1.25, NULL, buf, 640, 480);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IMediaDet_GetSampleGrabber(detector, &sg);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    if (SUCCEEDED(hr)) ISampleGrabber_Release(sg);
+    hr = IMediaDet_get_OutputStreams(detector, &count);
+    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
     ref = IMediaDet_Release(detector);
     ok(!ref, "Got outstanding refcount %d.\n", ref);
     ref = IBaseFilter_Release(&testfilter.filter.IBaseFilter_iface);
-- 
2.21.0




More information about the wine-devel mailing list