From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/Makefile.in | 2 +- dlls/mf/tests/transform.c | 109 +++++++++++++++++++++++++++++--------- include/codecapi.h | 3 ++ 3 files changed, 88 insertions(+), 26 deletions(-)
diff --git a/dlls/mf/tests/Makefile.in b/dlls/mf/tests/Makefile.in index 432400d4efc..13a6c1803de 100644 --- a/dlls/mf/tests/Makefile.in +++ b/dlls/mf/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mf.dll -IMPORTS = mf mfplat dmoguids mfuuid strmiids uuid wmcodecdspuuid ole32 user32 propsys msdmo d3d9 d3d11 dxva2 msvfw32 +IMPORTS = mf mfplat dmoguids mfuuid strmiids uuid wmcodecdspuuid ole32 user32 propsys msdmo d3d9 d3d11 dxva2 msvfw32 oleaut32
SOURCES = \ mf.c \ diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 41cc36b6884..9870616c518 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -46,6 +46,7 @@ #include "initguid.h"
#include "codecapi.h" +#include "icodecapi.h"
#include "d3d11_4.h"
@@ -265,12 +266,41 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO ok_ (file, line)((val).member == (exp).member, "Got " #member " " fmt ", expected " fmt ".\n", (val).member, (exp).member) #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
+const char *debugstr_propvariant(const PROPVARIANT *propvar, BOOL ratio) +{ + char buffer[1024] = {0}, *ptr = buffer; + UINT i; + + switch (propvar->vt) + { + default: + return wine_dbg_sprintf("??"); + case VT_CLSID: + return wine_dbg_sprintf("%s", debugstr_guid(propvar->puuid)); + case VT_UI4: + return wine_dbg_sprintf("%lu", propvar->ulVal); + case VT_UI8: + if (ratio) + return wine_dbg_sprintf("%lu:%lu", propvar->uhVal.HighPart, propvar->uhVal.LowPart); + else + return wine_dbg_sprintf("%I64u", propvar->uhVal.QuadPart); + case VT_VECTOR | VT_UI1: + ptr += sprintf(ptr, "size %lu, data {", propvar->caub.cElems); + for (i = 0; i < 128 && i < propvar->caub.cElems; ++i) + ptr += sprintf(ptr, "0x%02x,", propvar->caub.pElems[i]); + if (propvar->caub.cElems > 128) + ptr += sprintf(ptr, "...}"); + else + ptr += sprintf(ptr - (i ? 1 : 0), "}"); + return wine_dbg_sprintf("%s", buffer); + } +} + void check_attributes_(const char *file, int line, IMFAttributes *attributes, const struct attribute_desc *desc, ULONG limit) { - char buffer[1024], *buf = buffer; PROPVARIANT value; - int i, j, ret; + int i, ret; HRESULT hr;
for (i = 0; i < limit && desc[i].key; ++i) @@ -280,32 +310,10 @@ void check_attributes_(const char *file, int line, IMFAttributes *attributes, ok_(file, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr); if (hr != S_OK) continue;
- switch (value.vt) - { - default: sprintf(buffer, "??"); break; - case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break; - case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break; - case VT_UI8: - if (desc[i].ratio) - sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart); - else - sprintf(buffer, "%I64u", value.uhVal.QuadPart); - break; - case VT_VECTOR | VT_UI1: - buf += sprintf(buf, "size %lu, data {", value.caub.cElems); - for (j = 0; j < 128 && j < value.caub.cElems; ++j) - buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]); - if (value.caub.cElems > 128) - buf += sprintf(buf, "...}"); - else - buf += sprintf(buf - (j ? 1 : 0), "}"); - break; - } - ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0); todo_wine_if(desc[i].todo_value) ok_(file, line)(ret == 0, "%s mismatch, type %u, value %s\n", - debugstr_a(desc[i].name), value.vt, buffer); + debugstr_a(desc[i].name), value.vt, debugstr_propvariant(&value, desc[i].ratio)); PropVariantClear(&value); } } @@ -4054,6 +4062,25 @@ static void test_h264_encoder(void) ATTR_UINT32(test_attr_guid, 0), {0}, }; + const struct attribute_desc expect_codec_api_attributes[] = + { + ATTR_UINT32(CODECAPI_AVEncCommonRateControlMode, eAVEncCommonRateControlMode_CBR, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncCommonQuality, 65, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncCommonBufferSize, 72577, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncCommonMaxBitRate, 0, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncCommonMeanBitRate, 193540, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncCommonQualityVsSpeed, 33, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncH264CABACEnable, 0, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncH264PPSID, 0, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncH264SPSID, 0, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncMPVGOPSize, 0, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncMPVDefaultBPictureCount, 1, .todo = TRUE), + ATTR_UINT64(CODECAPI_AVEncVideoEncodeQP, 26, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncVideoMaxQP, 51, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncVideoMinQP, 0, .todo = TRUE), + ATTR_UINT32(CODECAPI_AVEncVideoMaxNumRefFrame, 2, .todo = TRUE), + {0}, + }; const struct attribute_desc output_sample_attributes_key[] = { ATTR_UINT32(MFSampleExtension_CleanPoint, 1), @@ -4071,10 +4098,12 @@ static void test_h264_encoder(void) MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12}; IMFSample *input_sample, *output_sample; IMFCollection *output_sample_collection; + const struct attribute_desc *desc; ULONG nv12frame_data_size, size; const BYTE *nv12frame_data; IMFMediaType *media_type; IMFTransform *transform; + ICodecAPI *codec_api; DWORD output_status; HRESULT hr; ULONG ret; @@ -4099,6 +4128,8 @@ static void test_h264_encoder(void) ok(hr == S_OK, "CoCreateInstance returned %#lx.\n", hr);
check_interface(transform, &IID_IMFTransform, TRUE); + todo_wine + check_interface(transform, &IID_ICodecAPI, TRUE); check_interface(transform, &IID_IMediaObject, FALSE); check_interface(transform, &IID_IPropertyStore, FALSE); check_interface(transform, &IID_IPropertyBag, FALSE); @@ -4202,6 +4233,34 @@ static void test_h264_encoder(void) winetest_pop_context(); }
+ hr = IMFTransform_QueryInterface(transform, &IID_ICodecAPI, (void **)&codec_api); + todo_wine + ok(hr == S_OK, "QueryInterface returned %#lx.\n", hr); + if (hr == S_OK) + { + for (desc = &expect_codec_api_attributes[0]; desc->key; ++desc) + { + PROPVARIANT propvar; + VARIANT var; + + hr = ICodecAPI_GetValue(codec_api, desc->key, &var); + todo_wine_if(desc->todo) + ok(hr == S_OK, "%s is missing.\n", debugstr_a(desc->name)); + if (hr != S_OK) + continue; + hr = VariantToPropVariant(&var, &propvar); + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + ret = PropVariantCompareEx(&propvar, &desc->value, 0, 0); + todo_wine_if(desc->todo_value) + ok(ret == 0, "%s mismatch, type %u, value %s.\n", + debugstr_a(desc->name), propvar.vt, debugstr_propvariant(&propvar, desc->ratio)); + + PropVariantClear(&propvar); + VariantClear(&var); + } + ICodecAPI_Release(codec_api); + } + check_mft_set_output_type(transform, output_type_desc, S_OK); check_mft_set_input_type(transform, input_type_desc, S_OK);
diff --git a/include/codecapi.h b/include/codecapi.h index b40d122c497..571d08ea1dd 100644 --- a/include/codecapi.h +++ b/include/codecapi.h @@ -242,6 +242,9 @@ DEFINE_GUID(CODECAPI_AVEncH264CABACEnable, 0xee6cad62, 0xd305, 0x4248, 0xa5, 0xe DEFINE_GUID(CODECAPI_AVEncH264SPSID, 0x50f38f51, 0x2b79, 0x40e3, 0xb3, 0x9c, 0x7e, 0x9f, 0xa0, 0x77, 0x5, 0x1); DEFINE_GUID(CODECAPI_AVEncH264PPSID, 0xbfe29ec2, 0x56c, 0x4d68, 0xa3, 0x8d, 0xae, 0x59, 0x44, 0xc8, 0x58, 0x2e);
+DEFINE_GUID(CODECAPI_AVEncMPVGOPSize, 0x95f31b26, 0x95a4, 0x41aa, 0x93, 0x03, 0x24, 0x6a, 0x7f, 0xc6, 0xee, 0xf1); +DEFINE_GUID(CODECAPI_AVEncMPVDefaultBPictureCount, 0x8d390aac, 0xdc5c, 0x4200, 0xb5, 0x7f, 0x81, 0x4d, 0x04, 0xba, 0xba, 0xb2); + DEFINE_GUID(CODECAPI_AVEncStatVideoOutputFrameRate, 0xbe747849, 0x9ab4, 0x4a63, 0x98, 0xfe, 0xf1, 0x43, 0xf0, 0x4f, 0x8e, 0xe9); DEFINE_GUID(CODECAPI_AVEncStatVideoCodedFrames, 0xd47f8d61, 0x6f5a, 0x4a26, 0xbb, 0x9f, 0xcd, 0x95, 0x18, 0x46, 0x2b, 0xcd); DEFINE_GUID(CODECAPI_AVEncStatVideoTotalFrames, 0xfdaa9916, 0x119a, 0x4222, 0x9a, 0xd6, 0x3f, 0x7c, 0xab, 0x99, 0xcc, 0x8b);