[PATCH v3 2/8] mfplat/buffer: Fix image copy function for IMC2/IMC4 buffers with odd height.

Giovanni Mascellani gmascellani at codeweavers.com
Thu Jun 16 08:58:13 CDT 2022


Il 16/06/22 14:33, Nikolay Sivov ha scritto:
> I don't understand this. Why would it use fractions of strides? And 
> doing one copy instead of two related to odd heights? Or does the 
> subject need adjusting?

Yeah, maybe it's better to explain; first, notice that when the height 
is even mine code and yours are precisely equivalent: copying x/2 lines 
of data with stride y and then other x/2 with the same stride y, but 
offsetted by a y/2, is precisely equivalent to copying x lines with 
stride y/2.

For example, suppose that width == 4, stride == 8 and lines == 4. You 
may represent the UV part of the image in this way (where "." denotes 
padding data):


If you use the approach currently in the code, you will first copy all 
the X data and then all the Y data. But the same data can also be 
represented as


I.e., with the double number of lines and half the stride. The code I am 
proposing "looks" at data in this way and does the copy with a single 
call to MFCopyImage().

Looking from this point of view, the change is correct, but not 
particularly useful. The point is that for odd heights the two 
approaches are different, and from my tests it seems that mine is correct.

Specifically, if width == 4, stride == 8 and lines == 5 the data will 
look like:


The current code will only copy the first two XX blocks (because it 
copies lines / 2 == 2 lines), but I think that Microsoft thinks that the 
third XX line is still part of the image. The new code will correctly 
copy all the five lines.

Does this make sense?

>>   static inline struct buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer 
>> *iface)
>> diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
>> index 1b5e8cf7ed5..52608c05929 100644
>> --- a/dlls/mfplat/tests/mfplat.c
>> +++ b/dlls/mfplat/tests/mfplat.c
>> @@ -6027,12 +6027,11 @@ static void test_MFCreate2DMediaBuffer(void)
>>               case MAKEFOURCC('I','M','C','2'):
>>               case MAKEFOURCC('I','M','C','4'):
>> -                for (j = ptr->height; j < length2 / stride; j++)
>> +                for (j = 0; ptr->height * stride + j * (stride / 2) < 
>> length2; j++)
>>                       for (k = 0; k < ptr->width / 2; k++)
>> -                        ok(data[j * pitch + k] == 0xff, "Unexpected 
>> byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k);
>> -                for (j = ptr->height; j < length2 / stride; j++)
>> -                    for (k = pitch / 2; k < pitch / 2 + ptr->width / 
>> 2; k++)
>> -                        ok(data[j * pitch + k] == 0xff, "Unexpected 
>> byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k);
>> +                        ok(data[ptr->height * pitch + j * (pitch / 2) 
>> + k] == 0xff,
>> +                                "Unexpected byte %02x at test %d row 
>> %d column %d.\n",
>> +                                data[ptr->height * pitch + j * (pitch 
>> / 2) + k], i, j, k);
>>                   break;
> It feels like this could be more readable. I see initial contents are 
> set to 0xff, so I'm not even sure what we are testing. What else could 
> it be if not 0xff?

Yeah, the image format is a bit involved so I have to do some trickery 
to do the right checks. The point is that what we set of 0xff is the 
buffer locked with _Lock(), therefore in its contiguous format. When we 
then lock it with _Lock2D() there will be a lot of padding bytes that 
are not necessarily set to 0xff (though they could be, I don't think 
they're guaranteed to be zero). What that test is checking is which 
bytes of the 2D buffer are really part of the image (i.e., they're not 
padding), and the result is that the last half-line of the UV section of 
a image of odd height is still considered part of the image (therefore 
the change made in the first hunk is appropriate).

You can try to keep the second hunk and revert the first one, and you'll 
see that the tests fail on Wine (but they don't on Windows).

Thanks, Giovanni.

More information about the wine-devel mailing list