mfplat: Add MFGetStrideForBitmapInfoHeader().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-03-12 18:39:10 +03:00 committed by Alexandre Julliard
parent a60b3985bf
commit d62f8f645a
4 changed files with 166 additions and 30 deletions

View File

@ -19,6 +19,7 @@
#define COBJMACROS
#include "mfplat_private.h"
#include "d3d9types.h"
#include "initguid.h"
#include "ks.h"
@ -1763,6 +1764,8 @@ struct uncompressed_video_format
{
const GUID *subtype;
unsigned int bytes_per_pixel;
unsigned int alignment;
BOOL bottom_up;
};
static int __cdecl uncompressed_video_format_compare(const void *a, const void *b)
@ -1772,33 +1775,57 @@ static int __cdecl uncompressed_video_format_compare(const void *a, const void *
return memcmp(guid, format->subtype, sizeof(*guid));
}
static HRESULT mf_get_image_size(REFGUID subtype, unsigned int width, unsigned int height, unsigned int *size)
static const struct uncompressed_video_format video_formats[] =
{
static const struct uncompressed_video_format video_formats[] =
{
{ &MFVideoFormat_RGB24, 3 },
{ &MFVideoFormat_ARGB32, 4 },
{ &MFVideoFormat_RGB32, 4 },
{ &MFVideoFormat_RGB565, 2 },
{ &MFVideoFormat_RGB555, 2 },
{ &MFVideoFormat_A2R10G10B10, 4 },
{ &MFVideoFormat_RGB8, 1 },
{ &MFVideoFormat_A16B16G16R16F, 8 },
};
struct uncompressed_video_format *format;
{ &MFVideoFormat_RGB24, 3, 3, 1 },
{ &MFVideoFormat_ARGB32, 4, 3, 1 },
{ &MFVideoFormat_RGB32, 4, 3, 1 },
{ &MFVideoFormat_RGB565, 2, 3, 1 },
{ &MFVideoFormat_RGB555, 2, 3, 1 },
{ &MFVideoFormat_A2R10G10B10, 4, 3, 1 },
{ &MFVideoFormat_RGB8, 1, 3, 1 },
{ &MFVideoFormat_L8, 1, 3, 1 },
{ &MFVideoFormat_NV12, 1, 0, 0 },
{ &MFVideoFormat_D16, 2, 3, 0 },
{ &MFVideoFormat_L16, 2, 3, 0 },
{ &MFVideoFormat_A16B16G16R16F, 8, 3, 1 },
};
format = bsearch(subtype, video_formats, ARRAY_SIZE(video_formats), sizeof(*video_formats),
static struct uncompressed_video_format *mf_get_video_format(const GUID *subtype)
{
return bsearch(subtype, video_formats, ARRAY_SIZE(video_formats), sizeof(*video_formats),
uncompressed_video_format_compare);
if (format)
}
static unsigned int mf_get_stride_for_format(const struct uncompressed_video_format *format, unsigned int width)
{
return (width * format->bytes_per_pixel + format->alignment) & ~format->alignment;
}
/***********************************************************************
* MFGetStrideForBitmapInfoHeader (mfplat.@)
*/
HRESULT WINAPI MFGetStrideForBitmapInfoHeader(DWORD fourcc, DWORD width, LONG *stride)
{
struct uncompressed_video_format *format;
GUID subtype;
TRACE("%#x, %u, %p.\n", fourcc, width, stride);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
subtype.Data1 = fourcc;
if (!(format = mf_get_video_format(&subtype)))
{
*size = ((width * format->bytes_per_pixel + 3) & ~3) * height;
}
else
{
*size = 0;
*stride = 0;
return MF_E_INVALIDMEDIATYPE;
}
return format ? S_OK : E_INVALIDARG;
*stride = mf_get_stride_for_format(format, width);
if (format->bottom_up)
*stride *= -1;
return S_OK;
}
/***********************************************************************
@ -1806,24 +1833,65 @@ static HRESULT mf_get_image_size(REFGUID subtype, unsigned int width, unsigned i
*/
HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size)
{
struct uncompressed_video_format *format;
unsigned int stride;
TRACE("%s, %u, %u, %p.\n", debugstr_mf_guid(subtype), width, height, size);
return mf_get_image_size(subtype, width, height, size);
if (!(format = mf_get_video_format(subtype)))
{
*size = 0;
return E_INVALIDARG;
}
switch (subtype->Data1)
{
case MAKEFOURCC('N','V','1','2'):
/* 2 x 2 block, interleaving UV for half the height */
*size = ((width + 1) & ~1) * height * 3 / 2;
break;
case D3DFMT_L8:
case D3DFMT_L16:
case D3DFMT_D16:
*size = width * format->bytes_per_pixel * height;
break;
default:
stride = mf_get_stride_for_format(format, width);
*size = stride * height;
}
return S_OK;
}
/***********************************************************************
* MFGetPlaneSize (mfplat.@)
*/
HRESULT WINAPI MFGetPlaneSize(DWORD format, DWORD width, DWORD height, DWORD *size)
HRESULT WINAPI MFGetPlaneSize(DWORD fourcc, DWORD width, DWORD height, DWORD *size)
{
struct uncompressed_video_format *format;
unsigned int stride;
GUID subtype;
TRACE("%#x, %u, %u, %p.\n", format, width, height, size);
TRACE("%#x, %u, %u, %p.\n", fourcc, width, height, size);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
subtype.Data1 = format;
subtype.Data1 = fourcc;
return mf_get_image_size(&subtype, width, height, size);
if (!(format = mf_get_video_format(&subtype)))
return MF_E_INVALIDMEDIATYPE;
stride = mf_get_stride_for_format(format, width);
switch (fourcc)
{
case MAKEFOURCC('N','V','1','2'):
*size = stride * height * 3 / 2;
break;
default:
*size = stride * height;
}
return S_OK;
}
/***********************************************************************

View File

@ -101,7 +101,7 @@
@ stdcall MFGetPluginControl(ptr)
@ stub MFGetPrivateWorkqueues
@ stub MFGetSockaddrFromNumericName
@ stub MFGetStrideForBitmapInfoHeader
@ stdcall MFGetStrideForBitmapInfoHeader(long long ptr)
@ stdcall MFGetSystemTime()
@ stdcall MFGetTimerPeriodicity(ptr)
@ stub MFGetUncompressedVideoFormat

View File

@ -92,6 +92,7 @@ static HRESULT (WINAPI *pMFAllocateWorkQueueEx)(MFASYNC_WORKQUEUE_TYPE queue_typ
static HRESULT (WINAPI *pMFTEnumEx)(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count);
static HRESULT (WINAPI *pMFGetPlaneSize)(DWORD format, DWORD width, DWORD height, DWORD *size);
static HRESULT (WINAPI *pMFGetStrideForBitmapInfoHeader)(DWORD format, DWORD width, LONG *stride);
static const WCHAR fileschemeW[] = L"file://";
@ -664,6 +665,7 @@ static void init_functions(void)
X(MFCreateMFByteStreamOnStream);
X(MFCreateTransformActivate);
X(MFGetPlaneSize);
X(MFGetStrideForBitmapInfoHeader);
X(MFHeapAlloc);
X(MFHeapFree);
X(MFPutWaitingWorkItem);
@ -3376,6 +3378,7 @@ static void test_MFCalculateImageSize(void)
UINT32 width;
UINT32 height;
UINT32 size;
UINT32 plane_size; /* Matches image size when 0. */
}
image_size_tests[] =
{
@ -3395,6 +3398,13 @@ static void test_MFCalculateImageSize(void)
{ &MFVideoFormat_A2R10G10B10, 1, 1, 4 },
{ &MFVideoFormat_A16B16G16R16F, 3, 5, 120 },
{ &MFVideoFormat_A16B16G16R16F, 1, 1, 8 },
/* YUV */
{ &MFVideoFormat_NV12, 1, 3, 9, 4 },
{ &MFVideoFormat_NV12, 1, 2, 6, 3 },
{ &MFVideoFormat_NV12, 2, 2, 6, 6 },
{ &MFVideoFormat_NV12, 3, 2, 12, 9 },
{ &MFVideoFormat_NV12, 4, 2, 12, 12 },
};
unsigned int i;
UINT32 size;
@ -3418,15 +3428,17 @@ static void test_MFCalculateImageSize(void)
image_size_tests[i].height, &size);
ok(hr == S_OK || (is_broken && hr == E_INVALIDARG), "%u: failed to calculate image size, hr %#x.\n", i, hr);
ok(size == image_size_tests[i].size, "%u: unexpected image size %u, expected %u.\n", i, size,
image_size_tests[i].size);
image_size_tests[i].size);
if (pMFGetPlaneSize)
{
unsigned int plane_size = image_size_tests[i].plane_size ? image_size_tests[i].plane_size :
image_size_tests[i].size;
hr = pMFGetPlaneSize(image_size_tests[i].subtype->Data1, image_size_tests[i].width, image_size_tests[i].height,
&size);
ok(hr == S_OK, "%u: failed to get plane size, hr %#x.\n", i, hr);
ok(size == image_size_tests[i].size, "%u: unexpected plane size %u, expected %u.\n", i, size,
image_size_tests[i].size);
ok(size == plane_size, "%u: unexpected plane size %u, expected %u.\n", i, size, plane_size);
}
}
}
@ -4473,6 +4485,60 @@ static void test_queue_com_state(const char *name)
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
}
static void test_MFGetStrideForBitmapInfoHeader(void)
{
static const struct stride_test
{
const GUID *subtype;
unsigned int width;
LONG stride;
}
stride_tests[] =
{
{ &MFVideoFormat_RGB8, 3, -4 },
{ &MFVideoFormat_RGB8, 1, -4 },
{ &MFVideoFormat_RGB555, 3, -8 },
{ &MFVideoFormat_RGB555, 1, -4 },
{ &MFVideoFormat_RGB565, 3, -8 },
{ &MFVideoFormat_RGB565, 1, -4 },
{ &MFVideoFormat_RGB24, 3, -12 },
{ &MFVideoFormat_RGB24, 1, -4 },
{ &MFVideoFormat_RGB32, 3, -12 },
{ &MFVideoFormat_RGB32, 1, -4 },
{ &MFVideoFormat_ARGB32, 3, -12 },
{ &MFVideoFormat_ARGB32, 1, -4 },
{ &MFVideoFormat_A2R10G10B10, 3, -12 },
{ &MFVideoFormat_A2R10G10B10, 1, -4 },
{ &MFVideoFormat_A16B16G16R16F, 3, -24 },
{ &MFVideoFormat_A16B16G16R16F, 1, -8 },
/* YUV */
{ &MFVideoFormat_NV12, 1, 1 },
{ &MFVideoFormat_NV12, 2, 2 },
{ &MFVideoFormat_NV12, 3, 3 },
};
unsigned int i;
LONG stride;
HRESULT hr;
if (!pMFGetStrideForBitmapInfoHeader)
{
win_skip("MFGetStrideForBitmapInfoHeader() is not available.\n");
return;
}
hr = pMFGetStrideForBitmapInfoHeader(MAKEFOURCC('H','2','6','4'), 1, &stride);
ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(stride_tests); ++i)
{
hr = pMFGetStrideForBitmapInfoHeader(stride_tests[i].subtype->Data1, stride_tests[i].width, &stride);
ok(hr == S_OK, "%u: failed to get stride, hr %#x.\n", i, hr);
ok(stride == stride_tests[i].stride, "%u: format %s, unexpected stride %d, expected %d.\n", i,
wine_dbgstr_an((char *)&stride_tests[i].subtype->Data1, 4), stride, stride_tests[i].stride);
}
}
START_TEST(mfplat)
{
char **argv;
@ -4524,6 +4590,7 @@ START_TEST(mfplat)
test_MFCreateTransformActivate();
test_MFTRegisterLocal();
test_queue_com();
test_MFGetStrideForBitmapInfoHeader();
CoUninitialize();
}

View File

@ -421,6 +421,7 @@ void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllo
void WINAPI MFHeapFree(void *ptr);
HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size);
HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size);
HRESULT WINAPI MFGetStrideForBitmapInfoHeader(DWORD format, DWORD width, LONG *stride);
HRESULT WINAPI MFGetPlaneSize(DWORD format, DWORD width, DWORD height, DWORD *size);
HRESULT WINAPI MFGetTimerPeriodicity(DWORD *periodicity);
HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,