This is not completely exact, and depending on how often ProcessInput and ProcessOutput are called the numbers may vary a bit, but this version seems to be consistent enough. We could very well ignore the checks too as GStreamer output doesn't seem to match.
We check that we can at least push two input samples at a time, which matches what Call of Duty Black Ops 3 is doing, as it is not checking ProcessInput result most of the time.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 6462594dae2..69ad4c2e5fc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6615,6 +6615,7 @@ static void test_h264_decoder(void) MFT_OUTPUT_DATA_BUFFER output; const BYTE *h264_encoded_data; ULONG h264_encoded_data_len; + IMFAttributes *attributes; IMFMediaType *media_type; IMFTransform *transform; ULONG i, ret, flags; @@ -6632,6 +6633,14 @@ static void test_h264_decoder(void) &transform, &class_id)) goto failed;
+ hr = IMFTransform_GetAttributes(transform, &attributes); + todo_wine + ok(hr == S_OK, "GetAttributes returned %#x\n", hr); + if (hr != S_OK) MFCreateAttributes(&attributes, 0); + hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1); + ok(hr == S_OK, "SetUINT32 returned %#x\n", hr); + IMFAttributes_Release(attributes); + /* no output type is available before an input type is set */
hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type); @@ -6826,6 +6835,7 @@ static void test_h264_decoder(void) ok(!output.pEvents, "got pEvents %p\n", output.pEvents); ok(status == 0, "got status %#x\n", status);
+ i = 0; sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); while (1) { @@ -6844,19 +6854,26 @@ static void test_h264_decoder(void) ret = IMFSample_Release(output.pSample); ok(ret == 0, "Release returned %u\n", ret);
- while (h264_encoded_data_len > 4) - { - hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - if (FAILED(hr)) break; - ok(hr == S_OK, "ProcessInput returned %#x\n", hr); - ret = IMFSample_Release(sample); - ok(ret <= 1, "Release returned %u\n", ret); - sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); - } - ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#x\n", hr); - EXPECT_REF(sample, 1); + hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + todo_wine + ok(hr == S_OK, "ProcessInput returned %#x\n", hr); + ret = IMFSample_Release(sample); + ok(ret <= 1, "Release returned %u\n", ret); + sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); + + hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + todo_wine + ok(hr == S_OK, "ProcessInput returned %#x\n", hr); + ret = IMFSample_Release(sample); + ok(ret <= 1, "Release returned %u\n", ret); + sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); + i++; } todo_wine + ok(i == 3, "got %u iterations\n", i); + todo_wine + ok(h264_encoded_data_len == 43479, "got h264_encoded_data_len %u\n", h264_encoded_data_len); + todo_wine ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#x\n", hr); ok(output.dwStreamID == 0, "got dwStreamID %u\n", output.dwStreamID); ok(!!output.pSample, "got pSample %p\n", output.pSample);
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 66 ++++++++++++++++++++++++++++++++++-- dlls/mf/tests/nv12frame.bin | Bin 0 -> 9600 bytes dlls/mf/tests/resource.rc | 3 ++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 dlls/mf/tests/nv12frame.bin
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 69ad4c2e5fc..e16df6112a3 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6610,19 +6610,23 @@ static void test_h264_decoder(void)
MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264}; MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12}; + const BYTE *h264_encoded_data, *nv12_frame_data; + ULONG h264_encoded_data_len, nv12_frame_len; MFT_OUTPUT_STREAM_INFO output_info; MFT_INPUT_STREAM_INFO input_info; MFT_OUTPUT_DATA_BUFFER output; - const BYTE *h264_encoded_data; - ULONG h264_encoded_data_len; + IMFMediaBuffer *media_buffer; + WCHAR output_path[MAX_PATH]; IMFAttributes *attributes; IMFMediaType *media_type; IMFTransform *transform; + DWORD status, length; ULONG i, ret, flags; + HANDLE output_file; IMFSample *sample; HRSRC resource; GUID class_id; - DWORD status; + BYTE *data; HRESULT hr;
hr = CoInitialize(NULL); @@ -6915,6 +6919,62 @@ static void test_h264_decoder(void) todo_wine ok(i == 5, "%u output media types\n", i);
+ /* and generate a new one as well in a temporary directory */ + GetTempPathW(ARRAY_SIZE(output_path), output_path); + lstrcatW(output_path, L"nv12frame.bin"); + output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %u\n", GetLastError()); + + resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA); + ok(resource != 0, "FindResourceW failed, error %u\n", GetLastError()); + nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); + nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource); + ok(nv12_frame_len == 9600, "got frame length %u\n", nv12_frame_len); + + status = 0; + memset(&output, 0, sizeof(output)); + output.pSample = create_sample(NULL, output_info.cbSize); + hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine + ok(hr == S_OK, "ProcessOutput returned %#x\n", hr); + ok(output.dwStreamID == 0, "got dwStreamID %u\n", output.dwStreamID); + ok(!!output.pSample, "got pSample %p\n", output.pSample); + ok(output.dwStatus == 0, "got dwStatus %#x\n", output.dwStatus); + ok(!output.pEvents, "got pEvents %p\n", output.pEvents); + ok(status == 0, "got status %#x\n", status); + if (hr == S_OK) + { + /* Win8 and before pad the data with garbage instead of original + * buffer data, make sure it's consistent. */ + hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer); + ok(hr == S_OK, "ConvertToContiguousBuffer returned %#x\n", hr); + hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length); + ok(hr == S_OK, "Lock returned %#x\n", hr); + todo_wine + ok(length == nv12_frame_len, "got length %u\n", length); + if (length == nv12_frame_len) + { + for (i = 0; i < 74; ++i) + { + memset(data + 80 * i + 78, 0xcd, 2); + memset(data + 80 * (80 + i) + 78, 0xcd, 2); + } + memset(data + 80 * 74, 0xcd, 6 * 80); + memset(data + 80 * 117, 0xcd, 3 * 80); + } + hr = IMFMediaBuffer_Unlock(media_buffer); + ok(hr == S_OK, "Unlock returned %#x\n", hr); + IMFMediaBuffer_Release(media_buffer); + + if (length == nv12_frame_len) + check_sample(output.pSample, nv12_frame_data, nv12_frame_len, output_file); + } + ret = IMFSample_Release(output.pSample); + ok(ret == 0, "Release returned %u\n", ret); + + trace("created %s\n", debugstr_w(output_path)); + CloseHandle(output_file); + ret = IMFTransform_Release(transform); ok(ret == 0, "Release returned %u\n", ret); ret = IMFSample_Release(sample); diff --git a/dlls/mf/tests/nv12frame.bin b/dlls/mf/tests/nv12frame.bin new file mode 100644 index 0000000000000000000000000000000000000000..9ceceb8fedbaace124ee5155566822fc2f441335 GIT binary patch literal 9600 zcmaF;8V)WYz$yfohyYm#5QqSpNZ{;QxM{CnBaFL*Fm4sXxQPhkvJl1vA{nPSY91sI zN5c=4Y(~=yD4UGt4`>-PTE2jah0*d9R4k0vAK+qPw7wjzFA)X8Xni?aUyioNK_$Xy z`+2ne3~M6Lw*8D`x&Q(omBa`^0eGrhxe7@XDaXD(dzLKoRt=bWf)I}o@Gn;Py?Xun z)!_FpQbY*|AV<|}6d49EfC?#qfxube^hMfBHDga-U81g)s8CRm`||8r6kQ~lC-+)) zX_BV!lGR#5ratAxP7f|5Ev3Y~wc;^{?>Nfs^P8}Gf19!VYtc0+mXw%x!R49V%Yc5P zJrY%3tAr9KCat=eM~Qh$j+xizWi7jKttD`p@YN%B31&%qDKYQnql(APGjH}8UP+NZ zF1>G6xl(pECFVJ0Zs<BwBJMNe;lWjsPY<2T-1sz!67!zxKREJ2we>}O%ZAks*7K&S zyU0~hV&0ST6SbG}p33){)bvf*C%-fLVC;QL%sZx{dO~%ha9qvg^!u~>3wM|-$zDK- zd5$|ub}zNI7t$7SHk+dQ;<nQHLz$GAx8Xw7#uHkT)Tc;J-#jVxSnrFa7iLppUdJR| zuasNo#L^31MYm-idb0P98*qG*?EI^E<BDYF)$@Iw4%4bPos5$>cI}dl7X{`ixCOND znALM)-MX{MNr$?OHpj>;3Z=w6wb1r#TjOg57b43xob}H0-ndX)g%a~lY<*lMkz8=f ze6M^_oPN#rOQ%<?q{KXtncB4__EYnFq|R9;7Cw^jTN87b67wcq-`=qz@8~%>uM}%3 z#d*u!o=KfQI|_z*2sFTfN2kCf7+fX*gL#r>N-%ip9t=);9`ykRKjb0c*|Tut8b-|n zh2d!Ufzr%qdV%DT(fk1^VPK`pX#RkdsH6E~q~?zu<uKR)tTAB_CbpxzGbK6@1`(o@ zXXNgHL4@dz^0Q|Vb@7gJL|qK4w@=+$x*j2l$c2+V5TeK|>YI1l2?qDOPfCN?wRHW` z^|vnF2EvoOw=Lebc=jZa%w!K3>`H;DM5WK3Jtm5Pi@lL$UmrujZHtj*aI;6vLxc?? X^j;qu4L?M<AhW2SUWR#h1H*d&)8J<o
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index 17adc3ed46c..5a2bf913672 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -25,3 +25,6 @@ wmadata.bin RCDATA wmadata.bin
/* @makedep: h264data.bin */ h264data.bin RCDATA h264data.bin + +/* @makedep: nv12frame.bin */ +nv12frame.bin RCDATA nv12frame.bin
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=109800
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
mf: mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6894: Test failed: got 8 iterations mf.c:6896: Test failed: got h264_encoded_data_len 35560
=== w7u_adm (32 bit report) ===
mf: mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6894: Test failed: got 9 iterations mf.c:6896: Test failed: got h264_encoded_data_len 34020
=== w7u_el (32 bit report) ===
mf: mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6887: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6894: Test failed: got 9 iterations mf.c:6896: Test failed: got h264_encoded_data_len 34020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index e16df6112a3..8f00a07d469 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6610,6 +6610,7 @@ static void test_h264_decoder(void)
MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264}; MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12}; + UINT32 input_id, output_id, input_count, output_count; const BYTE *h264_encoded_data, *nv12_frame_data; ULONG h264_encoded_data_len, nv12_frame_len; MFT_OUTPUT_STREAM_INFO output_info; @@ -6820,6 +6821,17 @@ static void test_h264_decoder(void) todo_wine ok(output_info.cbAlignment == 0, "got cbAlignment %#x\n", output_info.cbAlignment);
+ input_count = output_count = 0xdeadbeef; + hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count); + todo_wine + ok(hr == S_OK, "GetStreamCount returned %#x\n", hr); + todo_wine + ok(input_count == 1, "got input_count %u\n", input_count); + todo_wine + ok(output_count == 1, "got output_count %u\n", output_count); + hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id); + ok(hr == E_NOTIMPL, "GetStreamIDs returned %#x\n", hr); + resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA); ok(resource != 0, "FindResourceW failed, error %u\n", GetLastError()); h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/h264_decoder.c | 276 +++++++++++++++++++ dlls/winegstreamer/mfplat.c | 29 +- dlls/winegstreamer/winegstreamer_classes.idl | 6 + 5 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 dlls/winegstreamer/h264_decoder.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 0bcdb3eec65..3524cffb399 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -8,6 +8,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
C_SRCS = \ audioconvert.c \ + h264_decoder.c \ main.c \ media_source.c \ mfplat.c \ diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index e5870bc3b5d..b8d7b8e9fb1 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -123,6 +123,7 @@ void mf_destroy_wg_sample(struct wg_sample *wg_sample);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
+HRESULT h264_decoder_create(REFIID riid, void **ret); HRESULT audio_converter_create(REFIID riid, void **ret);
struct wm_stream diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c new file mode 100644 index 00000000000..2fafaea4fff --- /dev/null +++ b/dlls/winegstreamer/h264_decoder.c @@ -0,0 +1,276 @@ +/* H264 Decoder Transform + * + * Copyright 2022 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "gst_private.h" + +#include "mfapi.h" +#include "mferror.h" +#include "mfobjects.h" +#include "mftransform.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +struct h264_decoder +{ + IMFTransform IMFTransform_iface; + LONG refcount; +}; + +static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct h264_decoder, IMFTransform_iface); +} + +static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + struct h264_decoder *decoder = impl_from_IMFTransform(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IMFTransform)) + *out = &decoder->IMFTransform_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI transform_AddRef(IMFTransform *iface) +{ + struct h264_decoder *decoder = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&decoder->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); + + return refcount; +} + +static ULONG WINAPI transform_Release(IMFTransform *iface) +{ + struct h264_decoder *decoder = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&decoder->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); + + if (!refcount) + free(decoder); + + return refcount; +} + +static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n", + iface, input_minimum, input_maximum, output_minimum, output_maximum); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, + DWORD *inputs, DWORD output_size, DWORD *outputs) +{ + FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p stub!\n", iface, + input_size, inputs, output_size, outputs); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) +{ + FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + FIXME("iface %p, attributes %p stub!\n", iface, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + FIXME("iface %p, id %#lx stub!\n", iface, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + FIXME("iface %p, streams %lu, ids %p stub!\n", iface, streams, ids); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, + DWORD index, IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + FIXME("iface %p, flags %p stub!\n", iface, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + FIXME("iface %p, lower %I64d, upper %I64d stub!\n", iface, lower, upper); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + FIXME("iface %p, message %#x, param %Ix stub!\n", iface, message, param); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) +{ + FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) +{ + FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status); + return E_NOTIMPL; +} + +static const IMFTransformVtbl transform_vtbl = +{ + transform_QueryInterface, + transform_AddRef, + transform_Release, + transform_GetStreamLimits, + transform_GetStreamCount, + transform_GetStreamIDs, + transform_GetInputStreamInfo, + transform_GetOutputStreamInfo, + transform_GetAttributes, + transform_GetInputStreamAttributes, + transform_GetOutputStreamAttributes, + transform_DeleteInputStream, + transform_AddInputStreams, + transform_GetInputAvailableType, + transform_GetOutputAvailableType, + transform_SetInputType, + transform_SetOutputType, + transform_GetInputCurrentType, + transform_GetOutputCurrentType, + transform_GetInputStatus, + transform_GetOutputStatus, + transform_SetOutputBounds, + transform_ProcessEvent, + transform_ProcessMessage, + transform_ProcessInput, + transform_ProcessOutput, +}; + +HRESULT h264_decoder_create(REFIID riid, void **ret) +{ + struct h264_decoder *decoder; + + TRACE("riid %s, ret %p.\n", debugstr_guid(riid), ret); + + if (!(decoder = calloc(1, sizeof(*decoder)))) + return E_OUTOFMEMORY; + + decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; + decoder->refcount = 1; + + *ret = &decoder->IMFTransform_iface; + TRACE("Created decoder %p\n", *ret); + return S_OK; +} diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index b864dc187d2..22c4f259ad8 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -410,6 +410,7 @@ class_objects[] = { &CLSID_VideoProcessorMFT, &video_processor_create }, { &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create }, { &CLSID_WINEAudioConverter, &audio_converter_create }, + { &CLSID_MSH264DecoderMFT, &h264_decoder_create }, };
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) @@ -459,6 +460,21 @@ static const GUID *const wma_decoder_output_types[] = &MFAudioFormat_Float, };
+static WCHAR h264_decoderW[] = L"Microsoft H264 Video Decoder MFT"; +static const GUID *const h264_decoder_input_types[] = +{ + &MFVideoFormat_H264, + &MFVideoFormat_H264_ES, +}; +static const GUID *const h264_decoder_output_types[] = +{ + &MFVideoFormat_NV12, + &MFVideoFormat_YV12, + &MFVideoFormat_IYUV, + &MFVideoFormat_I420, + &MFVideoFormat_YUY2, +}; + static const struct mft { const GUID *clsid; @@ -495,13 +511,24 @@ mfts[] = ARRAY_SIZE(wma_decoder_output_types), wma_decoder_output_types, }, + { + &CLSID_MSH264DecoderMFT, + &MFT_CATEGORY_VIDEO_DECODER, + h264_decoderW, + MFT_ENUM_FLAG_SYNCMFT, + &MFMediaType_Video, + ARRAY_SIZE(h264_decoder_input_types), + h264_decoder_input_types, + ARRAY_SIZE(h264_decoder_output_types), + h264_decoder_output_types, + }, };
HRESULT mfplat_DllRegisterServer(void) { unsigned int i, j; HRESULT hr; - MFT_REGISTER_TYPE_INFO input_types[4], output_types[2]; + MFT_REGISTER_TYPE_INFO input_types[4], output_types[5];
for (i = 0; i < ARRAY_SIZE(mfts); i++) { diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index 90dc1dc839b..347ee906a52 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -73,3 +73,9 @@ coclass WINEAudioConverter { } uuid(2eeb4adf-4578-4d10-bca7-bb955f56320a) ] coclass CWMADecMediaObject {}; + +[ + threading(both), + uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d) +] +coclass CMSH264DecoderMFT {}
Several of the games using the transform call this function to set the MF_LOW_LATENCY attribute. It does nothing for us but returning a failure causes some of them to crash.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 2 -- dlls/winegstreamer/h264_decoder.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 8f00a07d469..3c988c58996 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6639,9 +6639,7 @@ static void test_h264_decoder(void) goto failed;
hr = IMFTransform_GetAttributes(transform, &attributes); - todo_wine ok(hr == S_OK, "GetAttributes returned %#x\n", hr); - if (hr != S_OK) MFCreateAttributes(&attributes, 0); hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1); ok(hr == S_OK, "SetUINT32 returned %#x\n", hr); IMFAttributes_Release(attributes); diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 2fafaea4fff..fdc0d6addeb 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -119,7 +119,7 @@ static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD i static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) { FIXME("iface %p, attributes %p stub!\n", iface, attributes); - return E_NOTIMPL; + return MFCreateAttributes(attributes, 0); }
static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=109803
Your paranoid android.
=== w7u_adm (32 bit report) ===
mf: mf.c:6897: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6897: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6897: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6897: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6897: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6897: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6904: Test failed: got 10 iterations mf.c:6906: Test failed: got h264_encoded_data_len 32365
=== w7u_el (32 bit report) ===
mf: mf.c:6904: Test failed: got 5 iterations mf.c:6906: Test failed: got h264_encoded_data_len 40388
=== debian11 (32 bit report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
Report validation errors: mf:mf prints too much data (44428 bytes)
=== debian11 (32 bit Arabic:Morocco report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (32 bit German report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (32 bit French report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (32 bit Hebrew:Israel report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (32 bit Hindi:India report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (32 bit Japanese:Japan report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (32 bit Chinese:China report) ===
mf: mf.c:5694: Test failed: MFCreateMemoryBuffer returned 0x8007000e Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00409085).
=== debian11 (64 bit WoW report) ===
Report validation errors: mf:mf has unaccounted for todo messages The report seems to have been truncated
=== debian11 (build log) ===
WineRunWineTest.pl:error: An error occurred while waiting for the task to complete: network read got a premature EOF (wait2/connect:AgentVersion.h:0/9) WineRunWineTest.pl:error: The test VM has crashed, rebooted or lost connectivity (or the TestAgent server died) WineRunWineTest.pl:error: The previous 2 run(s) terminated abnormally
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=109799
Your paranoid android.
=== w7u_adm (32 bit report) ===
mf: mf.c:6883: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6883: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6883: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6883: Test failed: ProcessInput returned 0xc00d36b5 mf.c:6890: Test failed: got 9 iterations mf.c:6892: Test failed: got h264_encoded_data_len 34020