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.
-- v8: 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.
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 0a2471d3849..21bcc86c8d1 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -5672,6 +5672,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-1d.bmp | Bin 0 -> 37938 bytes dlls/mf/tests/nv12frame-crop-2d.bmp | Bin 0 -> 59190 bytes dlls/mf/tests/nv12frame-crop.bmp | Bin 0 -> 37938 bytes dlls/mf/tests/resource.rc | 12 ++++++ dlls/mf/tests/transform.c | 63 +++++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100755 dlls/mf/tests/nv12frame-crop-1d.bmp create mode 100755 dlls/mf/tests/nv12frame-crop-2d.bmp create mode 100755 dlls/mf/tests/nv12frame-crop.bmp
diff --git a/dlls/mf/tests/nv12frame-crop-1d.bmp b/dlls/mf/tests/nv12frame-crop-1d.bmp new file mode 100755 index 0000000000000000000000000000000000000000..edd1111348829b8498b5e5f37735322a4e0fa964 GIT binary patch literal 37938 zcmZ?ry_U@Y24)Nl3>pj!3_%PG3?U2*42%p4VDSY|c`ye`yl!atKZ+>`gZ9q<m)ko> z!;sQ+G#ZZ7NkgOII2w+W=0$4iA5D*=>5-c0iBhvh)8lA*q%;jtQ~zjs98HhZOiz@W zHJTo&njSCd_Wd8l6of&<l>a9pri_LmrRgYQ%Ku}aa1@;M|I#QXKMY)^|3Bt3oqYYH zVGjwr(Qt%>1EuL<G#p36k<v6oP5q<kaWp+rGd)pi)@XVhO^=kOA!_O$O^;MfkE<Gu z{*Ph`!eBz=|5YG78jh5uqY07!mx01@nc)9bqnP|KSnl+H*>WfH^^b-<B<x1R5fToR zriamR91TZG(-1ZFkEX}b^hnM0M5$S$>2WkYQksUSsed#*QZ+qJ2~zq$iYW+#LZAN= zK{!b1|HM&Dei(ql5QNQ@|4$sn<cC45-~WjqJQ{}Nhao8JKw${NAoeIGKP*9E2*RUb zNPZZC!VVOMAPi!UV)DZh6ow!?8iwSDAt>xXVF<z?_9!MlEJ0xi!lPkGei(wn4ittU z3}TOB^1~7oh9Eo|hUAAKDC|IC80+^xYuScTOi385-~K;q{r3Oa%QlQ+O2PmZj;HSZ z&mP4Tgu$)<S*LDMpno*{A?a^493kOAX?hq9$I)=4G!0Qx|7dy~O^?(}Pn4Q9njS~f zBc*AGn)*l6BQ?`wWXa3_qnLs)=zQ=$s`J7BppuuPn36E)eDFUE6pm3J{s)a>^24C) z+5fPzXXNW24SPt~jfNv694Ji>qv1Fjj+CY$YU&?NkE7|4n(2vBvqsb7XnLeH4N+77 zXnLe-dNe)W{eKiw5C%u4{kK0d?Z4*n?omuh7#x}Q-x3s#@ALm_j$-n|;8Ej$%SVmm z>mLn!NZ5^rBP1LsO%J2tI2w+WrXgzTA5D*=>5-c0iBhvh)8lA*q%;jtQ~zjsq-uJ6 zO>J<Q+6KNJHIX_&IvS26C>$?Q8=RoFftQYrnn;xp7!60N1mn<1kE;ehSVnaxj+#iF zARP_IK^u-!s0}8Lg3%Bd4S|6Ufh?+nY-)onY8#k6Y9e)lbTk|XZ8%0!8$<<B8-!8Y zz@SkRsS~85;W%i+(UjW2UX$9ulG+Apj+#iFARP_IK^u+@R0i#xR5q|-)I{opXnUt_ zA9Z2G6v0W<g)Y;nYo6ewk!oV25q05&$Yp}mh0C3&Yu+-!k!oU)5_MsrkGV2+VXPl@ z%`;aXsU|MlKwY?g`>A_WhPS9}-n~;J)WnjP)P<c7qCQX;mOZ1cc~Kums)@(DsSA%x Td!J8T_^6S(=Dp7!sU`vdZ7@`l
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/nv12frame-crop-2d.bmp b/dlls/mf/tests/nv12frame-crop-2d.bmp new file mode 100755 index 0000000000000000000000000000000000000000..a62b084d6a5552b193df96489c38b7e73a7361c5 GIT binary patch literal 59190 zcmZ?rHCw>|24)Nl3>pj!3=Iqn3?U2*42%p4U~vYhJcI)wUpF-TAH@`eL3`)_%k7>2 z&z?OyB=Kn6QxNx{yfYgABfI<<jsMa3A1(h!ZW<WP|06f<N9+HQ9rvU0KN|m|<^RY| z1EcXj8vmp1|B;&pM)Uv3jr(EH{=1~x_kR>q5C#!b{-21LG9<_TL30+PaZf?qgYr(q zl>f(ua{LQU`hRH@lOF~y)BhiHnLc#$|7hHkANQcJ8;yU;!VeUNLm7|8|7iS=mj5F+ z4UFdhksJ4*dTTWPN8^9A{2#e#U^M@a+_)bt|3`M*4}<t$)oAp86jKle6C(ewnh-f; z$Nxs-o`Sds<(&zU|CbHr_+KXYf7K`^KMa;T{a?1+Y3Szv(YPl+?m=NU8vm4qA1Dlm zG9Hcp(fA)N|3_{b7|s79H||08)@b~X#{X#fKXTK+X#O9$aX(uAkL<V~2Jt^7Na_D5 zrXUOoeg01@^ck|_e-ne0{*Ph`!eFS!zq#`NiKCeOFo^a0KQY#C=;r^?xF<jEL18x< z|CEIvC=7=(9*zIe_#Z9*M{XJz&Hp1e?m_j|X#9`H|7iI?a?`+Q{vWw<KU)5e?6@BW z@t?J9!~aoCK^Uyx{y%H|_8~j|m%VJm|4~dq7!39JKXvba_9&(x3~v3;I(2L4=Ks;S zry%Y@d1o~KM|Sx!8vmp5KU)5e+%zzn|3_}zkJkSqJMKs0e>DC_%m0y`21et5H2#Nf z`#-Ye<^NGkK^SyC_#f5zV91XD1(m$~KZ+>`gU$#4!-jJFM}7DoG>XX&gR*D;!^)lw z-TXfq_vFVtDC|b#pR(`+h2c=fqwzl)|D)yq$V~&I`G4fbJ*eIqjsMa3A1(h!ZW<WP z|06f<N6Y__9rwc^{!Nc}{~yH^gu#(%|Lu=V8?xhnn#a5Uk75eK;K;Q9mP0xI-{=3= z9L3~^!K23imX8{TZvG#Qd-CHR6n3NWPg(eZ!f+_#(fA*Y|IzY)<fehq{6BKz9#n6Q z#{X#ikCy)<Hw}#D|B)N_qvij|j{9K{|F5YHE}ta{P}};~qxO%6KM5f)n*OL90;Bnl zgw%KTER{q5HL2y_C2E5cBzgZVwXMH&Y}9^ILSQufsT=~M>5r7;H=6&cocu^F|5i~Q zkQDuAsc!wUQTs^=fzj}%atMs3KT?w4X#S^i@>@k>`kO*+Fp;F_KRc1?VAOt6LV)VQ zKN|m}1pjFIr+NY;DfmZx_-9cakQV;g)CO6j_LC9<)DHga(eNiF_|J}pKb1pZH2sm3 z{vxRjqDZp-Y!J0U*r@%agaEaJKWH@kNeTYZ^iS;sIGX-QN`I!*2KFRbe^!&)z;e`n zQbK^*!LK<Q{-gx|X!@si0vt_$B&ELwDueb;lB_>VW$PP8?H>()QbIttkGe2o3Msaq zJu5hgy3l3%sQsjb0ChuOaMDl<|3)L~!U>V2g#OvH%LJ(lmphHxPf7?-H}sbY4z=(P zQlc&_^dTkm&z?0`rY?;28?~R55TI`8n=22s@L#rpx^Vq=QbPai*;DtZ3~!CvPf7?- zIrQ(H8e-vJ@{+o+^8qQLfA(zD2kOGIXQTF$5(3l>{iqK^E&PvnQx_hYMoQ?PJ^MbN Vy6{ossQsjb0ChwEeg04je*hgt#OVM4
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/nv12frame-crop.bmp b/dlls/mf/tests/nv12frame-crop.bmp new file mode 100755 index 0000000000000000000000000000000000000000..e0d7d92048246befd3e8b1bf401b2212c9899e57 GIT binary patch literal 37938 zcmZ?ry_U@Y24)Nl3>pj!3_%PG3?U2*42%p4VDSY|c`ye`Xui+?KZ+>`gGY`3Egv<G zh9RZtXfzzDlZHmaaWot$&5P93Kbjs#(<3$06QyR2rpM9rNNF0PrvB0NNZs^!y!*fA zC?-D)j!gS+d1Tsu)8pNvn36C!GVQ<pk!k;fqCSjbO2VM*+5fPzXQN?ANf?6kj)o(3 z($Hu)j)o&BKMfW<njS~f<6udPAa{(W$I<i%N(X}lkETcJrpJ<(|AR&``C-uc;D1=> zga45wFGn#YVbJ;De^lp#|JkSRjbe(z;MV`FQ@2LLkfJaIrNPl~q)uKO4ad=N1m&l} zf=AQiXnGthX%Xa((eyZ)9zp3~u;9`3NY(VXY{UQTQA~aqtl$1W3xt<#_@6b3$qxfi z7_Q&`f1<haD5fL~V*UP41Yt_d7}X02!_jc0JTHR65QIn56lGxv3PTVc4ad=N91Ljy zlommFFt}wXy8#r2AUu@)Fc{np3PTVc3~m|9ZUBWL2oGgH3<kG@!VrXml>Sc~#pH)U zq0j$`g+BkM1SySTO2Pmdj;odl{vX8@gu!yB|I3y;jfNqm>1Z?@sgs6A!*MhmDb0)2 z)IXXYN7ExU(-Wm;ji$%Z^hjwMqNe`Q^hn+G*l6^B)hH%E3?@YWUp66<eEp+g4+%R^ z7*2@%e@SrCD5fL~T&Dj&<}!UW3@HgiklxX7q)r+d4ad=N1m&l}f=AQiXnGthX%Xa( z(eyZ)9zp3~u;9`3NZs_P+xP#{C?-D)BBuO57BPi<{i9(I3A>0X|4&3r`Tx41VH8sm z2JM~yFSmD&h9M<k2+}(mj?_s*qv1Fjj-dQBSnz0i98HgdB`t#7F`6Dn(<3My3>G|^ z9!JyTU`dN0cZ{Y-s-{OxY6DAZ8>l&IB6WgvG#m$QIGR!$*auM?gi+hTpivX46QrZz zIB3H$lG-3Do7y0Y+6HEinn;}>9Sz4p8;)622NOrZXb6mkzyOE96l#NstEdf@QQN>( zqb5=(NJqnQ<b>m@OVkF(sBPe-Q4^^Xq@&?Da>DV%Yifhb)Hd+-sEO1G($R1nLE-p5 zpSti-BX!MtpFdJfJl;)Rcw}1C2kOGIXVf(>>cdDivE(InVdsNW_oxhSQQ5qEr$(rW z%QjFKuHSC1OkEi3M_u#Gl}D<HK}ytxg+9v!sSB4oQP;d>f+N+$MkDIN36X-6s0&@D iQ`bDfNh8%n-9GBVh$#(J2JM|xHn3sTMCycSdnW*TbX1Z6
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index ff7fb6d8b0c..dff5719dd3b 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -93,6 +93,18 @@ 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-1d.bmp */ +nv12frame-crop-1d.bmp RCDATA nv12frame-crop-1d.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 28b746f1622..b04698cea8f 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -8681,7 +8681,7 @@ 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 = 82, crop_height = 84, nv12_aligned_width = 128; const DWORD extra_width = actual_width + 0x30; const DWORD nv12_aligned_extra_width = 192; const struct attribute_desc rgb32_with_aperture[] = @@ -8724,6 +8724,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, crop_height, .required = TRUE), + {0}, + }; const struct attribute_desc rgb32_default_stride[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), @@ -8755,6 +8762,13 @@ 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, crop_width, crop_height, .required = TRUE), + {0}, + }; const struct attribute_desc rgb555_default_stride[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), @@ -8935,6 +8949,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 * crop_height * 3 / 2, + .compare = compare_nv12, .compare_rect = {.top = 12, .right = 82, .bottom = 84}, + .dump = dump_nv12, .size = {.cx = crop_width, .cy = crop_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 * crop_height * 3 / 2, + .compare = compare_nv12, .compare_rect = {.top = 12, .right = 82, .bottom = 84}, + .dump = dump_nv12, .size = {.cx = nv12_aligned_width, .cy = crop_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 { @@ -9156,6 +9194,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-crop.bmp", + .input_buffer_desc = use_2d_buffer ? rgb32_crop : NULL, + .output_type_desc = nv12_crop, .output_bitmap = L"nv12frame-crop.bmp", .output_bitmap_1d = L"nv12frame-crop-1d.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}; @@ -9516,6 +9563,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 * crop_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; @@ -9542,7 +9594,7 @@ static void test_video_processor(BOOL use_2d_buffer) input_info.cbSize = actual_width * actual_height * 2; check_mft_get_input_stream_info(transform, S_OK, &input_info); } - else if (test->input_type_desc == rgb32_no_aperture) + else if (test->input_type_desc == rgb32_no_aperture || test->input_type_desc == rgb32_crop) { input_info.cbSize = 82 * 84 * 4; check_mft_get_input_stream_info(transform, S_OK, &input_info); @@ -9589,10 +9641,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 { @@ -9616,8 +9669,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); @@ -9626,6 +9677,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 ba8b2d545f7..d96f82b62eb 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -994,8 +994,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;
I removed the implementation, and changed the tests to use `rgb32frame-crop.bmp` to avoid problematic cropping of the full-sized input. We don't need an implementation currently since there are no cases of this in the wild, and the D3D-aware case can't be tested anyway.
The issue can be fixed by passing an aligned width to `MFCalculateImageSize()` if NV12 is used, and fixing up the output buffer. This requires a locally allocated sample, for which it's probably possible to use the `MFT_OUTPUT_STREAM_PROVIDES_SAMPLES` pathway with little modification.
This is ready for further review now.
This merge request was approved by Elizabeth Figura.
Is that actually the case? GStreamer has a default alignment for any given format, but we can and do change that. That's the point of all that complicated alignment logic we have. Is some component rejecting alignment _below_ the default?
See my comment higher up. Alignment in gstreamer is hard-coded to 4 for NV12, and when d3d-awareness is enabled, we allocate the sample buffer, which ends up being too small for gstreamer to use.
Where is it hard-coded? gst_video_info_align_full() does specify 4-byte alignment, but as far as I can tell, if you manually fill any part of the GstVideoInfo structure, that'll be respected. I couldn't easily find any code that depends on 4-byte alignment. Of course it could exist, if it's the default, but it's not clear to me that's what you're saying, or you'd presumably be pointing to something more concrete.
On Mon Aug 4 22:55:17 2025 +0000, Elizabeth Figura wrote:
Is that actually the case? GStreamer has a default alignment for any
given format, but we can and do change that. That's the point of all that complicated alignment logic we have. Is some component rejecting alignment _below_ the default?
See my comment higher up. Alignment in gstreamer is hard-coded to 4
for NV12, and when d3d-awareness is enabled, we allocate the sample buffer, which ends up being too small for gstreamer to use. Where is it hard-coded? gst_video_info_align_full() does specify 4-byte alignment, but as far as I can tell, if you manually fill any part of the GstVideoInfo structure, that'll be respected. I couldn't easily find any code that depends on 4-byte alignment. Of course it could exist, if it's the default, but it's not clear to me that's what you're saying, or you'd presumably be pointing to something more concrete.
The `fill_planes()` helper in `gst-plugins-base/gst-libs/gst/video/video-info.c` called from `gst_video_info_align_full()` sets the minimum alignment. Apparently, setting an alignment manually in `GstVideoInfo` can only increase it. If I set `plane_align = 1` in `wg_transform_read_data()`, gstreamer still can't fit the output in the buffer.
This merge request was approved by Rémi Bernon.