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.
-- v3: 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 | 77 ++++++++++++++++++++++++---- 4 files changed, 76 insertions(+), 9 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 zcmZ?rHS1*n12YB&1`P%VhByWWh6Dx%21W)2us8!$9>Rf;uLA@BQ-(wTzYYxj|9bUm z((u`{|6dOVOtJq1|6d6V{J)w+d^RxfKV>-d|JlIM|7TaPCJmoG`~NHw9<Vr|Lby|w zZYfRo2>qk+PefiGHt~&F-d$O}`u}P|`0UyLtC28r9;7Q<Q}h2>B>Y-a^ZzI&B@8V8 zzt*%wsq3)DKT=$S<6Tqp|7s+R90vo*9y)Q48SX^2Iq1;FxPl(n*!W0s4@w6E8Ry7$ zQ!W0{+kbQjccR)ZbSU4hpv5gHehFdZI2cGa;rJiC`EGc}zvch4nwF%s?LmD3q_#aV z?Fyp8kes|shkQpk?UGWjldqOG`G1hb|A>iC(#tz=`wv^4k4KD{yh)ZCq_#aV^~zw$ zLxaa1(D)~z%mcUoNNfWT6F2lwGw8w{y&Xx2PeMG=s;(Or@lPn6(d7q0xP#+!5Y$Vw zssB;OX=qgzT++1s55}uk|Gz{EK7026rNMwTHUD24V0?_kvLDnp1h?(!(7q?sh9El* z2RO_JI?j>p9}@A8qg{yXkCDNqetCBcPdgtx_KQWHP`<<|k0Tz*tsjPMoKw4Q!c*Rn zm;dQgzY|Iq^oxJ$=R30NE^^Ywkd1%*<48E$eB^`?E%e|CclxDW{B6v^o&QJUpVsLF zd;DAeU#)40b6o(=bvq=E-{Wj25NQt1GIR*!J6gvpvF6hy{;AyVgS88Y_2bY{NB?#P zRonkGif34Sqtk;nUTM*mz-J}}<sJ6?kGkFmH0Fbh(c@vD_|%Jk`sX{Gbr-&P#w9mo z;~#(fj!-*;s$qyLZ1IUx5bo4VyZGDpgzOpE{7+f@uRMG9|A1gk&HpQhG`9S|Qq%JP z%GIm?FC(<}7g-)U7D#EkonrmacE-?-gMmy#B*s59-eGNkfvWG(?HzjYj|g{A-Xj{* zu$)^4i(6u7Xjy=>UIwk<qa!9d{8q09mvtnor(w90RBw^%ej@adRQ`{~|G>02h=@m$ z(>B!1K^gx<j{lLAhsepx&@du5Y=?rr5gGp@AYO@0dnoZwOdEj6yh%|TpU5@@v3?x! z>hP3(DD6LJ{Z42<=!j|m(W{)m6F;=B<3@D+4`8^X#4Ekh85Vm`%Kwp;|3~AWwDCV^ z`k=V{r&1dNB@dAkmss+{NNXz$NdBiZ{-N!|iK|!tAH^hu!P&F_Ct|_4*7@QRr>JcY zihF4MQCg0Sn7GFhXV~JApcsz)La4ouE>CH^QA_`jiGOOvAEoAuwD_kqyr`ugN4O7` z^oyRq3Gu0we<?MGVE9oh{wOtPq{Tm|j;8}Ax4t8oZU%XLQQQ55@;kab!F)?7?nm2y zwCT5ySx(_<=i?G5*#4(d{1QrM)XoPqGmp%8Ay~eln@eW7g`U3&@d?EXz2s>YU!;a3 zdOQpipHz24)f0+uba{HkFClwK&L6aj7ic&Rn)FDbd(h*T5T8)I&`W+a{z(}7!;>Zm z#W%V<!TO(2`;SWULp8q*Hg}`PFCjj?@;4!SvRAMEKcev2v;VWHjI)Sb^Ml+MAQUh3 zlBZkTQ#s7Zjzb!x_blj~E}=Y+EKjfaC1lTti~oj(|JhW=Sq%;USEFMBX@XF^P)(jd zJAv$cL~4Gfa+p&)4k<AYYy6|92Q>cKhKBzn;r7n|XF+)B`u}H1!Sss%;Tpf~o&U2z zc<K88**I|4()IsWqhkVX0=l*T38XVh(*20g3yOOXMvr@>@(*kK4=ul=*AFD+eFAYv ziCKd-4nbiK!sy{nh>sL6^s3uNMEnoJaK{?I15gjqrT(W;8Gw=hL3s{@3B@<M`~c*; zVHN+NwjBtQ(zXMsCD6Vj)Xu;fhUCQM0OUK2v^zj<pi2G+#XSgv;*=Cjt@t0Hup96= z1eJ9lj9#7*;v?k|to1*=+W!>R3j-eh1C{QO;*YE{5Xs$C$^R6_Be{Kmz=nqZ1A^N- z{|AEb()IrXNx^5&{tp}s7%ALB3H0^Q`+gukx$#A@K2RM4!q7T~=&&CQVGeQwQn(LD zy2WDuX#CSLPYO)>A4m+w5>K>BFGR(Ed*}bvAPgNRBzg>&!uB1Z_CL{ODKTL_Le+!{ zO!~i?5O$vae>DixD*go~{Xa_vCMqut<#=_T{yz|eNoiw%)Pm|7B5^2zwm$N_Ka5Q% zU&7_dh*MJ1!H|uABIAbW@(tZQ64E?T`5&!(ASI4ysg`E(56W{O49ZKSVDxwxDE?55 zf9L7{&w?<teNU*J0dM~gR5+vCOG3EQEbWr$hC!A8L2(blqw!B%KY_%!#+K&5@egX- zfiSdvhp`?2O&p#tY23btw<B=a1Fs*c5DwVFW+aGFCH`sL&coG)81nH0YGZ&fDQygp zT4=rVn%dyXY9w%$AfUGOuSe}44S#qD5KMk&N7EmbLtr%j!BgMr)q_9%U7|KPhU9%B z{7-G`FOAxd6aj?O-)Q(#IRr-2-)Q=Shrr;^e=DgCmcc#0nwa{J+SacewI3-02&cc% z@TYPJjHbWQ^al@t!Jq#oQXRlOPgMC&b?YaN+K&hU!s%}`{HYxRh|njd{X=crCyu6n zqzD*I|Aayyo7x}?Dfo#P|Dm?^*`xL&MF64LKYMmG{HYuQqv>xn{lP<E@aMlkYJ*U? z=ZR|nQ``E$QTvf1fN=U74Sy<!z-am#O@HtZ82tH9liI)%?s=lhe`;H=Ich&r1Q1St zqv22G5ExB=qv;PG0)s#Q!JSGI24Vlx#9FwaqxKUD0eDc+gh9ymvu9~yE!@yi`w4{r zJg8{GAY}V!{L>`Z;f4|p{{||9_Rgj25pdLgLLorq;BOcWe?;nAx}H$zpFJxuiMr5v z`l$Vg5Eu=ALLori)F&{B)bzJZfVyzGBO>;R$$!+feVM?h{iETJ2mwO5@9bG~CF;Uh zUxe+%q<`w#Zmu+H|7iFlLV$4kKY5S3@YF4Y?Zl*i>e_zt-l+Yf;g1Lb!s$QiJ#}H( zQ-tlrq`w#9`%0I{?YJ9gaG06{~?dM@Nomec4E$b#4EUH){WA_#;AqaQa86r3Gu$ 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 dfe3bddd454..00b7dba54b7 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -1165,9 +1165,11 @@ static void enum_mf_media_buffers(IMFSample *sample, const struct sample_desc *s ok(hr == S_OK, "GetBufferByIndex returned %#lx\n", hr); ok(i < sample_desc->buffer_count, "got unexpected buffer\n");
- callback(buffer, sample_desc->buffers + i, context); - - IMFMediaBuffer_Release(buffer); + if (i < sample_desc->buffer_count) + { + callback(buffer, sample_desc->buffers + i, context); + IMFMediaBuffer_Release(buffer); + } winetest_pop_context(); } ok(hr == E_INVALIDARG, "GetBufferByIndex returned %#lx\n", hr); @@ -2143,7 +2145,7 @@ static IMFSample *create_sample_(const BYTE *data, ULONG size, const struct attr IMF2DBuffer2 *buffer2d2; BYTE *buffer, *scanline; IMFSample *sample; - DWORD length; + DWORD length, max_length; LONG stride; HRESULT hr; ULONG ret; @@ -2166,9 +2168,10 @@ static IMFSample *create_sample_(const BYTE *data, ULONG size, const struct attr IMFMediaType_Release(media_type); }
- hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length); + hr = IMFMediaBuffer_Lock(media_buffer, &buffer, &max_length, &length); ok(hr == S_OK, "Lock returned %#lx\n", hr); if (!desc) ok(length == 0, "got length %lu\n", length); + size = min(size, max_length); if (!data) memset(buffer, 0xcd, size); else memcpy(buffer, data, size); hr = IMFMediaBuffer_Unlock(media_buffer); @@ -8576,9 +8579,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), @@ -8619,6 +8623,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), @@ -8650,6 +8661,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), @@ -8830,6 +8850,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 = 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_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 { @@ -9051,6 +9095,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}; @@ -9411,6 +9464,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; @@ -9484,10 +9542,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 { @@ -9511,8 +9570,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); @@ -9521,6 +9578,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 cf5b47edf68..c6e5f577628 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))) + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, &samples->dwStatus))) 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 e466a9289b1..923afecdbac 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))) + if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, &samples->dwStatus))) 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 9db484c033f..25af199d138 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); +HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, DWORD *flags); 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 c1ce9897ef1..258f52e0fcf 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))) + if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, &samples->dwStatus))) 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 4086b586d76..07b16eb96dc 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -988,8 +988,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))) + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, sample, &samples->dwStatus))) { wg_sample_queue_flush(decoder->wg_sample_queue, false);
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index fd28cd150da..2e0ffa32f3e 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))) + if (SUCCEEDED(hr = wg_transform_read_mf(encoder->wg_transform, samples->pSample, &samples->dwStatus))) 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 5f270c13550..84914f04b6d 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))) + if (FAILED(hr = wg_transform_read_mf(impl->wg_transform, output_sample, &samples->dwStatus))) 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 116dbb1f3ec..73dca5ba310 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) +HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, DWORD *flags) { struct wg_sample *wg_sample; IMFMediaBuffer *buffer; diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 09b2ee647b3..dda47b68444 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))) + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, &samples->dwStatus))) 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 07b16eb96dc..b5b44fe8f53 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,8 +951,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, UINT32 sample_size; LONGLONG duration; IMFSample *sample; - UINT64 frame_size, frame_rate; - GUID subtype; + UINT64 frame_rate; DWORD size; HRESULT hr;
@@ -960,15 +967,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) @@ -988,6 +993,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))) { wg_sample_queue_flush(decoder->wg_sample_queue, false);