Windows uses a smaller alignment than gstreamer for some formats, for example NV12. This means we cannot use MFCalculateImageSize() to get the output sample size. Commit 7b79e3a87b1e switched to calling it instead of GetOutputStreamInfo() to fix some game bugs.
-- v5: winegstreamer: Call wg_format_get_max_size() to get the video decoder output sample size. winegstreamer: Do not pass a sample size to wg_transform_read_mf(). mf/tests: Add a video processor NV12 test with a width alignment of 2. mfplat/tests: Add NV12 650 x 850 to image_size_tests.
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mfplat/tests/mfplat.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 6fe3f40cd93..c38a77d4edc 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -5631,6 +5631,7 @@ image_size_tests[] = { &MFVideoFormat_NV12, 3, 2, 12, 9, 192, 9, 64 }, { &MFVideoFormat_NV12, 4, 2, 12, 0, 192, 12, 64 }, { &MFVideoFormat_NV12, 320, 240, 115200, 0, 115200, 115200, 320 }, + { &MFVideoFormat_NV12, 650, 850, 828750, 0, 897600, 828750, 704 },
/* YUV 4:2:0, 12 bpp, planar, half stride (the secondary plane has * the same height, half the width and half the stride of the
From: Conor McCarthy cmccarthy@codeweavers.com
GStreamer has a minimum NV12 alignment of 4. --- dlls/mf/tests/nv12frame-crop-2d.bmp | Bin 0 -> 54582 bytes dlls/mf/tests/nv12frame-crop.bmp | Bin 0 -> 49686 bytes dlls/mf/tests/resource.rc | 8 ++++ dlls/mf/tests/transform.c | 64 ++++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 dlls/mf/tests/nv12frame-crop-2d.bmp create mode 100644 dlls/mf/tests/nv12frame-crop.bmp
diff --git a/dlls/mf/tests/nv12frame-crop-2d.bmp b/dlls/mf/tests/nv12frame-crop-2d.bmp new file mode 100644 index 0000000000000000000000000000000000000000..133a90514817454166495b4ae57a794db5b257db GIT binary patch literal 54582 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 ZenKHYi%>_HNyzrIXAx>?!5aMb0|0jrK}!Gt
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/nv12frame-crop.bmp b/dlls/mf/tests/nv12frame-crop.bmp new file mode 100644 index 0000000000000000000000000000000000000000..bf1d38c0387bc7e997393fb5d989cc134144bd21 GIT binary patch literal 49686 zcmZ?rHS1*n12YB&1`P%VhByWWh6Dx%21W)2us8!$9>Rf;uNxZvk75eKpuO||mG;j6 ztCy}P36F+31z`?Kv!mfYF!^>g+(*M5l>bHw9!>9~>3yW6b&x+t)B9+82c?6Nf=AQ) zXnG$hX&vOx(eyr~()%TWN&iPN1!3Sk{r@rN=_HNKfW~r0!<>RJ2c_B3a37d_I~wkz z;SS1wBL$D9_tEq|QqnrepQGu0G`)k;!AQZQ>3uZ4kCe0y^5<xJA5!Uk<uZZ)qnLs) zSnl|L*>Xpc$7e>voPsb1rP<MNADDbQ8t$Xv4$6Nc1&^lp(eyr2(mKeWqv?G#y@S%h zNWr7&eKfs~l(Y`==V*E#Qt5r7xzhhpOhFjL`u?97>r3+Z%xIWX5aysXI~wi-lW#}E zeKg!b`ER7)(eyr=-bYGW2l;a}y^p4MP&ybXcr?9_ruUJO)<OOpP47c0y=R}i_kR>q z5C*4i{m(jei{$Z{(J-eV%t2{(G~5R!-;Rd+Xt;y&-$=ou>3uZ4kCe0y^5<xJA5HI| zbTCrzXnG$_?;|CxgZw#~-iK6r4~%;Me-u*?24zqGhn77hd3<Ix%qa+SP?{YL_kqc` zqv1Xp?x6fPQt)VcA5HHgC9Q+}Ihx)_(>o{~j1)YY-bd5>NJ;A;e~za2A(h@WKji%% z#T10W<A(p1j~hrHpBW8v3c?(eW=F$)VDjx~xQ~WADF2NVJeuA|)B8wC>mYxQruWhG z4oU|j1&^lp(eyr2(mKeWqv?G}rFYO>LZg_pyRk>ZYc#w@)4*sN7)=ACX<#%BjHZFn zG%%V5M$^D(8W>FjqiJ9?4UDD%YNmnL)CN~pBLQj~{(97OTtPY-GNU1bD+F+f(=p9l zqBb~&RLrcVw&9mXO~)0aqaiaIGPptjmpC2M%t~s5Wys|WwGCf6YC5hU9Sxb$kiiuK zxWwt0W+qY{AeS>#H+<r#>A1plG-O6Y23H8+5~p99$)+~QLUuc~4bL7m9aoT!hRkTl z;0gg;;&e<ifz$?}$mI;R4G$bO9aoT!hRkTl;0gg;;&e<in$!lC$mI;R4c8ns9aoT! zhRkTl;0gg;;&e<i$fd$4do%<_Ltr!nXb}PpR0i#xOV=YHl?`tgH62%o(lcZPCQ%nU zPe-JfrR%9{w!oxO({Y6;Jws-h0CnMVN8~g^U9*=7jGB%sMClna=1SCsvA)P@hPq~( zD~+0tD@5rTGAHj*7oNI>oMxzN_Q`vrrsE1xdWKBYd+Nfnr^soBx@JecA2l6Uh|)7; jKIBmsK5jrxGt@QvL*A(AxI&bkA%h&lqwLWTASMI=IopSZ
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index 873d373e079..8349e908898 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -93,6 +93,14 @@ nv12frame.bmp RCDATA nv12frame.bmp /* @makedep: nv12frame-2d.bmp */ nv12frame-2d.bmp RCDATA nv12frame-2d.bmp
+/* Generated from running the tests on Windows */ +/* @makedep: nv12frame-crop.bmp */ +nv12frame-crop.bmp RCDATA nv12frame-crop.bmp + +/* Generated from running the tests on Windows */ +/* @makedep: nv12frame-crop-2d.bmp */ +nv12frame-crop-2d.bmp RCDATA nv12frame-crop-2d.bmp + /* Generated from running the tests on Windows */ /* @makedep: nv12frame-grabber.bmp */ nv12frame-grabber.bmp RCDATA nv12frame-grabber.bmp diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 4578dbac591..9bf314a73c8 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -8664,9 +8664,10 @@ static void test_video_processor(BOOL use_2d_buffer) };
const MFVideoArea actual_aperture = {.Area={82,84}}; - const DWORD actual_width = 96, actual_height = 96, nv12_aligned_width = 128; + const DWORD actual_width = 96, actual_height = 96, crop_width = 94, nv12_aligned_width = 128; const DWORD extra_width = actual_width + 0x30; const DWORD nv12_aligned_extra_width = 192; + const MFVideoArea crop_aperture = {.Area={94,96}}; const struct attribute_desc rgb32_with_aperture[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), @@ -8707,6 +8708,13 @@ static void test_video_processor(BOOL use_2d_buffer) ATTR_RATIO(MF_MT_FRAME_SIZE, extra_width, actual_height, .required = TRUE), {0}, }; + const struct attribute_desc nv12_crop[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, crop_width, actual_height, .required = TRUE), + {0}, + }; const struct attribute_desc rgb32_default_stride[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), @@ -8738,6 +8746,15 @@ static void test_video_processor(BOOL use_2d_buffer) ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4), {0}, }; + const struct attribute_desc rgb32_crop[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4), + ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &crop_aperture, 16), + {0}, + }; const struct attribute_desc rgb555_default_stride[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), @@ -8918,6 +8935,30 @@ static void test_video_processor(BOOL use_2d_buffer) .sample_time = 0, .sample_duration = 10000000, .buffer_count = 1, .buffers = &nv12_extra_width_buffer_2d_desc, }; + const struct buffer_desc nv12_crop_buffer_desc = + { + .length = crop_width * actual_height * 3 / 2, + .compare = compare_nv12, .compare_rect = {.top = 12, .right = 82, .bottom = 96}, + .dump = dump_nv12, .size = {.cx = crop_width, .cy = actual_height}, + }; + const struct sample_desc nv12_crop_sample_desc = + { + .attributes = output_sample_attributes, + .sample_time = 0, .sample_duration = 10000000, + .buffer_count = 1, .buffers = &nv12_crop_buffer_desc, + }; + const struct buffer_desc nv12_crop_buffer_2d_desc = + { + .length = nv12_aligned_width * actual_height * 3 / 2, + .compare = compare_nv12, .compare_rect = {.top = 12, .right = 82, .bottom = 96}, + .dump = dump_nv12, .size = {.cx = nv12_aligned_width, .cy = actual_height}, + }; + const struct sample_desc nv12_crop_sample_2d_desc = + { + .attributes = output_sample_attributes, + .sample_time = 0, .sample_duration = 10000000, + .buffer_count = 1, .buffers = &nv12_crop_buffer_2d_desc, + };
const struct transform_desc { @@ -9139,6 +9180,15 @@ static void test_video_processor(BOOL use_2d_buffer) .output_sample_desc = &rgb32_sample_desc, .output_sample_2d_desc = &rgb32_sample_desc, .todo = TRUE, }, + { /* Test 25 */ + .input_type_desc = rgb32_crop, .input_bitmap = L"rgb32frame.bmp", + .input_buffer_desc = use_2d_buffer ? rgb32_crop : NULL, + .output_type_desc = nv12_crop, .output_bitmap = L"nv12frame-crop.bmp", .output_bitmap_2d = L"nv12frame-crop-2d.bmp", + .output_buffer_desc = use_2d_buffer ? nv12_crop : NULL, + .output_sample_desc = &nv12_crop_sample_desc, .output_sample_2d_desc = &nv12_crop_sample_2d_desc, + .delta = 2, /* Windows returns 1, Wine needs 2 */ + .todo = TRUE, /* Would need special handling to convert gstreamer NV12 buffer to Windows alignment */ + }, };
MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12}; @@ -9499,6 +9549,11 @@ static void test_video_processor(BOOL use_2d_buffer) output_info.cbSize = actual_width * actual_height * 3 / 2; check_mft_get_output_stream_info(transform, S_OK, &output_info); } + else if (test->output_sample_desc == &nv12_crop_sample_desc) + { + output_info.cbSize = crop_width * actual_height * 3 / 2; + check_mft_get_output_stream_info(transform, S_OK, &output_info); + } else if (test->output_sample_desc == &rgb555_sample_desc) { output_info.cbSize = actual_width * actual_height * 2; @@ -9572,10 +9627,11 @@ static void test_video_processor(BOOL use_2d_buffer) output_sample = create_sample_(NULL, output_info.cbSize, test->output_buffer_desc); hr = check_mft_process_output(transform, output_sample, &output_status);
+ todo_wine_if(test->output_sample_desc == &nv12_crop_sample_desc) ok(hr == S_OK || broken(hr == MF_E_SHUTDOWN) /* w8 */, "ProcessOutput returned %#lx\n", hr); if (hr != S_OK) { - win_skip("ProcessOutput returned MF_E_SHUTDOWN, skipping tests.\n"); + skip("ProcessOutput returned %#lx, skipping tests.\n", hr); } else { @@ -9599,8 +9655,6 @@ static void test_video_processor(BOOL use_2d_buffer) ok(ret <= test->delta || broken(test->broken), "2d got %lu%% diff\n", ret); }
- IMFCollection_Release(output_samples); - output_sample = create_sample_(NULL, output_info.cbSize, test->output_buffer_desc); hr = check_mft_process_output(transform, output_sample, &output_status); ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); @@ -9609,6 +9663,8 @@ static void test_video_processor(BOOL use_2d_buffer) ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); ok(length == 0, "got length %lu\n", length); } + ret = IMFCollection_Release(output_samples); + ok(ret == 0, "Release returned %lu\n", ret); ret = IMFSample_Release(output_sample); ok(ret == 0, "Release returned %lu\n", ret);
From: Conor McCarthy cmccarthy@codeweavers.com
The size is not used. We could perhaps check it against the maximum size of the MF sample, but it would be more relevant to check the maximum size against the size GStreamer requires, which is unknown in this function. --- dlls/winegstreamer/aac_decoder.c | 7 +------ dlls/winegstreamer/color_convert.c | 7 +------ dlls/winegstreamer/gst_private.h | 3 +-- dlls/winegstreamer/resampler.c | 7 +------ dlls/winegstreamer/video_decoder.c | 3 +-- dlls/winegstreamer/video_encoder.c | 2 +- dlls/winegstreamer/video_processor.c | 5 +---- dlls/winegstreamer/wg_sample.c | 3 +-- dlls/winegstreamer/wma_decoder.c | 7 +------ 9 files changed, 9 insertions(+), 35 deletions(-)
diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c index 727c516f044..9e6c5c20cb2 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/aac_decoder.c @@ -544,7 +544,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct aac_decoder *decoder = impl_from_IMFTransform(iface); - MFT_OUTPUT_STREAM_INFO info; HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -559,11 +558,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, if (!samples->pSample) return E_INVALIDARG;
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) - return hr; - - if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, - info.cbSize, &samples->dwStatus, NULL))) + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, &samples->dwStatus, NULL))) wg_sample_queue_flush(decoder->wg_sample_queue, false); else samples->dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE; diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index c5c7141f4ce..938d8b7b6f2 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -651,7 +651,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct color_convert *impl = impl_from_IMFTransform(iface); - MFT_OUTPUT_STREAM_INFO info; HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -666,11 +665,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, if (!samples->pSample) return E_INVALIDARG;
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) - return hr; - - if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, - info.cbSize, &samples->dwStatus, NULL))) + if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, &samples->dwStatus, NULL))) wg_sample_queue_flush(impl->wg_sample_queue, false);
return hr; diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 60e0c3af8bc..d50c9fa63fb 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -166,8 +166,7 @@ HRESULT wg_transform_push_quartz(wg_transform_t transform, struct wg_sample *sam struct wg_sample_queue *queue); HRESULT wg_transform_push_dmo(wg_transform_t transform, IMediaBuffer *media_buffer, DWORD flags, REFERENCE_TIME time_stamp, REFERENCE_TIME time_length, struct wg_sample_queue *queue); -HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, - DWORD sample_size, DWORD *flags, bool *preserve_timestamps); +HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, DWORD *flags, bool *preserve_timestamps); HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *sample); HRESULT wg_transform_read_dmo(wg_transform_t transform, DMO_OUTPUT_DATA_BUFFER *buffer);
diff --git a/dlls/winegstreamer/resampler.c b/dlls/winegstreamer/resampler.c index 5e38243ac2b..910d109c2c6 100644 --- a/dlls/winegstreamer/resampler.c +++ b/dlls/winegstreamer/resampler.c @@ -519,7 +519,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct resampler *impl = impl_from_IMFTransform(iface); - MFT_OUTPUT_STREAM_INFO info; HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -537,11 +536,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_TRANSFORM_NEED_MORE_INPUT; }
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) - return hr; - - if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, - info.cbSize, &samples->dwStatus, NULL))) + if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, &samples->dwStatus, NULL))) wg_sample_queue_flush(impl->wg_sample_queue, false);
return hr; diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index a65f1781f96..b588e080004 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -989,8 +989,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, } }
- if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, sample, - sample_size, &samples->dwStatus, &preserve_timestamps))) + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, sample, &samples->dwStatus, &preserve_timestamps))) { wg_sample_queue_flush(decoder->wg_sample_queue, false);
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index f26bec66c84..41291928660 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -541,7 +541,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, if (!samples->pSample) return E_INVALIDARG;
- if (SUCCEEDED(hr = wg_transform_read_mf(encoder->wg_transform, samples->pSample, 0, &samples->dwStatus, NULL))) + if (SUCCEEDED(hr = wg_transform_read_mf(encoder->wg_transform, samples->pSample, &samples->dwStatus, NULL))) wg_sample_queue_flush(encoder->wg_sample_queue, false);
return hr; diff --git a/dlls/winegstreamer/video_processor.c b/dlls/winegstreamer/video_processor.c index 3e327228e65..587be98c98b 100644 --- a/dlls/winegstreamer/video_processor.c +++ b/dlls/winegstreamer/video_processor.c @@ -695,7 +695,6 @@ static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD f MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct video_processor *impl = impl_from_IMFTransform(iface); - MFT_OUTPUT_STREAM_INFO info; IMFSample *output_sample; HRESULT hr; BOOL playback_mode, provide_samples; @@ -709,8 +708,6 @@ static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD f return MF_E_TRANSFORM_TYPE_NOT_SET;
samples->dwStatus = 0; - if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) - return hr;
if (FAILED(IMFAttributes_GetUINT32(impl->attributes, &MF_XVP_PLAYBACK_MODE, (UINT32 *) &playback_mode))) playback_mode = FALSE; @@ -731,7 +728,7 @@ static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD f IMFSample_AddRef(output_sample); }
- if (FAILED(hr = wg_transform_read_mf(impl->wg_transform, output_sample, info.cbSize, &samples->dwStatus, NULL))) + if (FAILED(hr = wg_transform_read_mf(impl->wg_transform, output_sample, &samples->dwStatus, NULL))) goto done; wg_sample_queue_flush(impl->wg_sample_queue, false);
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c index 83f7163d0c9..2fc2679337f 100644 --- a/dlls/winegstreamer/wg_sample.c +++ b/dlls/winegstreamer/wg_sample.c @@ -338,8 +338,7 @@ HRESULT wg_transform_push_mf(wg_transform_t transform, IMFSample *sample, return hr; }
-HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, - DWORD sample_size, DWORD *flags, bool *preserve_timestamps) +HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, DWORD *flags, bool *preserve_timestamps) { struct wg_sample *wg_sample; IMFMediaBuffer *buffer; diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 312dec2034e..78f45f489c0 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -535,7 +535,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct wma_decoder *decoder = impl_from_IMFTransform(iface); - MFT_OUTPUT_STREAM_INFO info; HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -553,11 +552,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_TRANSFORM_NEED_MORE_INPUT; }
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) - return hr; - - if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, - info.cbSize, &samples->dwStatus, NULL))) + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, &samples->dwStatus, NULL))) wg_sample_queue_flush(decoder->wg_sample_queue, false);
return hr;
From: Conor McCarthy cmccarthy@codeweavers.com
Windows uses a smaller alignment than GStreamer for some formats, for example NV12. This means we cannot use MFCalculateImageSize() to get the output sample size. Commit 7b79e3a87b1e switched to calling it instead of GetOutputStreamInfo() to fix some game bugs.
Fixes video decode failure in a Resident Evil Village cutscene. --- dlls/winegstreamer/video_decoder.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index b588e080004..598d44cea9d 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -102,6 +102,7 @@ struct video_decoder wg_transform_t wg_transform; struct wg_transform_attrs wg_transform_attrs; struct wg_sample_queue *wg_sample_queue; + struct wg_format wg_output_format; /* for calculating sample size */
IMFVideoSampleAllocatorEx *allocator; BOOL allocator_initialized; @@ -754,6 +755,13 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF else hr = try_create_wg_transform(decoder, output_type);
+ mf_media_type_to_wg_format(output_type, &decoder->wg_output_format); + if (!decoder->wg_output_format.major_type) + { + FIXME("Failed to get output wg format.\n"); + hr = MF_E_INVALIDMEDIATYPE; + } + IMFMediaType_Release(output_type);
if (FAILED(hr)) @@ -943,9 +951,8 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, UINT32 sample_size; LONGLONG duration; IMFSample *sample; - UINT64 frame_size, frame_rate; + UINT64 frame_rate; bool preserve_timestamps; - GUID subtype; DWORD size; HRESULT hr;
@@ -961,15 +968,13 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, if (!(sample = samples->pSample) && !(decoder->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES)) return E_INVALIDARG;
- if (FAILED(hr = IMFMediaType_GetGUID(decoder->output_type, &MF_MT_SUBTYPE, &subtype))) - return hr; - if (FAILED(hr = IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_SIZE, &frame_size))) - return hr; - if (FAILED(hr = MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size, &sample_size))) - return hr; - if (decoder->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) { + /* GetOutputStreamInfo() is bugged for some games, and MFCalculateImageSize() + * for some formats uses a smaller stride alignment than GStreamer does */ + if (!(sample_size = wg_format_get_max_size(&decoder->wg_output_format))) + return E_INVALIDARG; + if (decoder->temp_buffer) { if (FAILED(IMFMediaBuffer_GetMaxLength(decoder->temp_buffer, &size)) || size < sample_size) @@ -989,6 +994,9 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, } }
+ /* In cases where the caller supplies the sample, and GStreamer requires a + * larger stride alignment than Windows, e.g. NV12, this call may fail, and + * the output buffer would need to be converted to the smaller alignment. */ if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, sample, &samples->dwStatus, &preserve_timestamps))) { wg_sample_queue_flush(decoder->wg_sample_queue, false);