From 77c25c86af8b61fc825f32257ff51292c0c6e775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 28 Apr 2022 12:24:37 +0200 Subject: [PATCH] mf/tests: Use real audio data for WMA encoder / decoder tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of silent data. This shows some difference in the FFmpeg decoded data, with the data delayed by half a buffer, explaining the additional data we decode. The audiodata.bin resource has been generated with: gst-launch-1.0 audiomixer name=mix ! \ audio/x-raw,format=F32LE,rate=22050,channels=2 ! \ filesink location=dlls/winegstreamer/tests/audiodata.bin \ audiotestsrc freq=400 volume=0.2 num-buffers=1 \ samplesperbuffer=22050 ! mix. \ audiotestsrc freq=600 volume=0.2 num-buffers=1 \ samplesperbuffer=22050 timestamp-offset=20000000 ! mix. Signed-off-by: RĂ©mi Bernon Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mf/tests/audiodata.bin | Bin 0 -> 179928 bytes dlls/mf/tests/mf.c | 175 +++++++++++++++++++++++------------ dlls/mf/tests/resource.rc | 10 +- dlls/mf/tests/wmadata.bin | Bin 49071 -> 0 bytes dlls/mf/tests/wmadecdata.bin | Bin 0 -> 28672 bytes dlls/mf/tests/wmaencdata.bin | Bin 0 -> 4461 bytes 6 files changed, 123 insertions(+), 62 deletions(-) create mode 100644 dlls/mf/tests/audiodata.bin delete mode 100644 dlls/mf/tests/wmadata.bin create mode 100644 dlls/mf/tests/wmadecdata.bin create mode 100644 dlls/mf/tests/wmaencdata.bin diff --git a/dlls/mf/tests/audiodata.bin b/dlls/mf/tests/audiodata.bin new file mode 100644 index 0000000000000000000000000000000000000000..5bf3fa1575ce8b980ef68a5c83b70a1b8e4760f2 GIT binary patch literal 179928 zcmeI*f2>qxe#h}=6)G*1j%ekwx;n7Xy@1M41+IAK>``I4Dv`?{nyV!1WLN7L4H+~F zZiqQVV;~qa8`$=eu<2km9TS9Eg9UNsctC5$bkkhZbiHY87!%xFx7p;{7`e?x+xPc; z=k~w;*FQfduZ*BvX3le-Gv{-@&yNtF9S){=TRAs+pd50ic*XRmuJWBInDIq!YH1Wq zag8f%jDo4(**C%~X6|)owno8B+~eXOMZpaI(AC%R|6_cmt6dufGcw;b{<9oR@=q>1 zRt~u*ctyCC$GV#J`&v+RT(<*IOS2Gql=`eJ={8`ll|wR1T&-;fjCHd4{mtCD+lOh!f63gfIAf z<|{rcD);mGG5yzW^js&H;umiEk7y^1FLv=?aJevYZGaO2nT_h53aYyGwpaw)Hf54&tzCzxc4c0)MJXF_&xI2SMDGb7pS zvNt%7QTP|v_%GTOdlp8y_2o8A60KL^Pzu1G&N^#M0; zUK&jDAG|O0-gm7dv>(C_m;5*FhOnUTaXurmYiK7_cDdSX92bOtcGF*Ry~Nl8`T?rf z^{wI+L)KT&{Gn^mmrS6IOt#fc^6zG3#1-$1f~no+#%|{4BP@0GE4h9m4lemO&MUNj z>t}97jfRA@Uol!2l^dq7hG}~#}4CHx$ZLh8G376b7LCJ zJlf6lM%)1HWmq`t}XM+?yq=7;cwk^m-a$D?S}q@_CfMp*BzuUp?9lmM6?&CHoNhAB0dLw zkajZzeZ3L>f6TkfH8;}U=<$7Ny35@7Rs4A*m$}*n&L>R&gDbqu`$QJ?{Uhff!kLY^ z(SU5%nuwSekO~(AREuwcAq8E&9rxZe%3o+@lZP z>$0u%R|I}-8b5N)AJX0!TJNf>=%?m7H@1MEkLj;yFNA+~wbwYGP}$|OYdG%^9;d&V z1$;&%|LwvK`WIS9TIifxztocD#|Judt^pU1p>doKAK+6`fl z&y2!8S3AyeLH%D{?+;v`ko;MiE8UQCtxmaSyV4N9#^4>UxrO$?e%i=%x4H`dZbtcU zrWL#W8~Fb)kDq7a>)oD(+`pjlU)(pL@GmZVgLXo)*Tu^?w~!s=`hjqk&xd4+c0;y} z^A_=8*Gg$W^IJDLm*b1^Yg}~&#~+2ibk$*gjnPf6N!yqz?PZd_DQh#F;r}x;{29~b z=a~2}-1uVt9!&p{D}F)yVDy}u{%iUjD)+na6>Vm|;Bz5P+PUO9K0m^4SN!`9_cgTH zgo`h6Tu}YfG&lA=`T>SkyB__;lxPPtLw_%2D1g8Woq!<^3XjpSDA?o&JV!C7&7D6Me^cMeuFWhx9kZw3(UUyUd)SznK|pGt@`=xUSYw*yxIUUz(|R8=});{ zV)Rts0bWtO&BbRq4>9{srOM|=?{imN$#KH|9d7T7Q84kiJKBtb8GhSMb?85+op-T4QcDD-yoM(vF&_7T-;lekx3u2Ck z$s$*Mfc}F}b=9Z&HOBY2$=zu%)m^UlDE-RZ?`FTxYO85Sv^d6Q^h=H>vbHO6Y)w*f z;Z2UMnd1Hk$xhB8^O*~aIkyns?0V}t?r5xap~!zna=D8;+=C!&>udAq z<`s=4oQJ5~?0V}v{CwW)S{Gl>u`-u950D&oVb#0ABrotjQCw2a#n16R(K_i$d{>!x z0p|l|ue&X-nPy~r-%ohO3~g(&XWh&mevOf5TU;9NG??yb zS3FMt!||i;%mMl>Dv!A$*JjfVZn{o?#O(b^gLXF)AGzMOQ7~iM+~D(kZX7-2K7B0; zruLRAw&|Z}opS^4bKOHFbIo_?N4W8%8$L!qMO=5I&+&bTaGyJK1K)cH+&h}&XMI2A zJV3aN_m1KbSNI*@2bi~n?|t+*&Ze;4l{nUBkbY%)yIp+`*D)mYK{NEY8+j-VW^7B} zT3#{x^Ao;{Oz)$g8#Dcs`{0#`pUv+zT$TP~u0HEp^e?lVzGiCY+^KgXJ_o-?|1@)6cOM+) z=b^jL4L%rgY&f>7-RPw<$Bk>+FI>iXXW}O3GcxYCOyf5$De&3QD!H+H=_iD(1rRqwop+9NDWbsc>9T;aXtAdXBHT zK;JMejx(~koG+*>@3TIJ-Z~erD$`f^_eCyT2RFUJLMWp?hi0<#I;|F_^#*QIo@V)gUhbq{sYAm9ADGF zzX{iHULo7T`GVGY*SLcF0}OKSZiY6y>JIu1YEQV?{xw5iGa3EQ%+MFj$WQvV^NQB6 zn|&@EFQC0py2yPbS|?rn9N#CHy}wCb;2c0$#rccm@Nh1^#5ruP=R8KX*3I5mR&J*M zp~2@h;cME*ywSIeSJUQx)og3$;!d0UPX5lzIqwjPuEBkznZ2)!X?GJAyW}(ejM?eJ z6!)s;P5urfCC+J-4!Dfx9%l4Q*IE>DpUt(E>!c}ijW)ge`yS;LRr-{f-0jBcbEZl^ zG@M$ zrsNv>;&E3wO+Q27J@@PLDY=Mqrf;glJtl_Vc1O7%HSxIH`(jG&O37ia$T?_wpL6U{ zsXFC2+F^I99Cw)h2IV;JgXmYvaa?CD%PGex$0^4t$0^4t#~mWeD97blPB~6FPC3qN zajM6W{dq=WW}lm=9>;T&9X#9I>{O3aJi7wXEiz1j$EhBtdYtNUs>i7w zr+QpIwo>CNshewDWj>}-<0=_vpmCKNSE+H88du4fN{y>zJi@nbcHE=JReDWM<0=`$ zrE!%SSE+H8njfe6ahe~;91NQyr}=Tr8+eF07hC$68>jhk%o$*AoaV=I&qOUw^|(%6 zi&H(0IRKg;m(P*Y{5a-GF-K1G<1|0c=E!M&9P=Qx&WW#a@+jkX?sr<}#ODHQofEBd z5?I$j>zpwES?io=ofFnL(K;urX`ppZ^0iL1&WYAJv9(UL&WYAJ(K;urvB#P;M(b6w zW=@eY9a^ta>s21|wJNnYq4!`TCbAlZmb`s^(vV^$5s8vCm0GV->s8vCm0GWoV=&Iz3r(ke2l$>~?*Z*Q!1^RBSSxneY2N|X zhh5M8RB+mNfctFLh1I?TTrb#rK>H4)`Q8KCcR>3N*xm!$cfj`^(7pq#FVEfs+IK+v z4rt#2-*Z6w4lt+U0jK@rcs|L#I@&)@`^VWHa@s$R@xtq&{p0dIzrtv6RmTS?*(pa zoM@es;d~Ep?E{`_A8_phu6@AS3tanvYaej!1MYi(Yaejm16=!nQ=5C*jqgdd@4)q) ze9r;xJHVK~Q_l7P*FNCP%d|bfwGX)O0ls%QgoC#`);Q5RC&OCjMC+XJ%z^R2TIWRT zoLrl-=Cal~(K;tw4;H)RGirEdrwdaX`QF5ve3v3Aaesl*0hhJQ%uiyB`IpYdRBBwM z##Lrf8jQwOc0%Q5A5*Dul|H7j{ZbkRj<`lMWzAycxHC6I!D#T%)8_f(HlJx=ww{X5cNtQMzwoa%9!AE)_onjhDn8>jhk`P{gf zhkb6G=EwQmxDQ^5v=6xU0oVLE&5zUkxK2C7(EPZL=Ew0&#pcFoejN4W&z#MT)BLzd z^W!u>PV?g~FjjLtbwAkLIL(jK{5aL)7{@$iW0~n2W^db32M*9a;EZ3p&|wTknhW=( z!HhoV;(8j)@G*DeN$oqJeFuEcfyNT>$bH+fMq!4IL~nP4?FCK z#`qF6+2h7cvd4?5A9S{Noc52?{&9`9^flPtaoRsF%J+^NTp96P%(c!l{s`F)7p~#j zgW?kQs5U2Db_L^VF}T4EJi<6i*qBO$tL*W7 z%_QHtc}sj>fU&jIuFV!V@(|A=p?$zLKTh-Gc($PVamsN!mE)A-qEOwz_u^(}8BRG) z`+z6kcDScvo~QN!XH9ta@VvokAMlh6#{5>EjcOlo-veCxfODN-4{+@Ru6o?SBN5MU zxrf-`v=6xU0oOj@z6ZGW0cY&Om(1&j?E$WRz{y@Kob~}vL*+5%qOu3L_5r6By35%f z;MxbAYXy6NYaei}bCRr%SPzD}IBT3}ofF2MTx47YvO_K(Q>k&4+IN6CIkwix)Oi>4 zYLbrYouZzOM$-)(A-AFZl2eYOuFSZT%FWKkRBBu$=g?9YzTw(~;t3b8VJ$C&0mgD8 zyPNN8*qBO~SN{_#C;~6Hzc$i&H(0XNS+bqlcnkK7GyA z-r_i+*mkXRtj~)9)k&4 zX&7Mqxv@RKwGTM=z8Y7__e{$7jyrlN<$H){a?iW5ZD}yQYn}ETVE@x+QtoS9_AK){ zFvHv_GxC$Z?YyEj?5ZnLo`KWn7P!*IPB5*L&ep2bdX?PkaGlovajDj;tTGQ6+CPrx z3v0PHT;F$zd8|kdyReGq5J+AibE3%e8xue0S|^#GhSEhBFNnAXk-b!p3ug{^El%~g zG?bW&XjG45-;Z0d+^HU?eFp{~^je(iapa{%PW3pSe^>ZjIhf)Rr+vUxk5i6Qj?=ya zWVZ)A!zsskhEtB?*|YYKV{J3`i@VQh|2W2-tnj_#w0|5qqu?69VH^&$e_Rx(t4HDPBpHQ^$+@EDmAWB<0>_-GE}$vm`aVS zq&CQY>^Y6A)VRv?9qk{deFro@j`^qs=BOI&AICUF&5z6H#%X?BJ2aSgY$mv0FuiMe zE{m~kPV?iKf3Y^@IknSzm5jIgq@1r+sr4#T_6BgaR;AXfWDd^5&ep2bdX*imS6OGi z6|{d`r1dI!Ua56XnEUfU6l|?ZtyjtO{Bd`b^?}Ur+ir^WgG`O=W`5nL9LK(jQ)fNH zDaR?tJ$n%^XW9-1AORl=6*lq#i*2j`57II?Hg%ajdD(aLRG4lTf0M z-0PI%I-$rs)Z%)leFv1|Y|TooSIIMC<+wbTHb@t#guw0&8&@t#d+6U>$3l*cvBV=Y%<8)Xy;Ib**!v`Ei;bSJ=)tCD`0J&5w)t z9(6W1PV?imUS(?$^N>+vZk*A2m1(d!a>bRd_c`|$s8n6(|5K@!`8~4x=dQ^9%Vz%$ zryQ4ZK6!>yj?;RTmf@7+I{!QFvB#R_Mmdgo>8m`$DaWO(@8Oi=Shs<-PPEPm_ZRDw zX#tcZzxvl8%ed(~mIK_vCwNFx}Hm^|%iE9H|}` zE^-fx-Xi)JtQMzw9Qy`7=v0r>z5{udQ;uUV&4}^lPW3p|<7_W*+N8Pk3H~>{X|F9Chop*y2VWidds5V!bApJWZV&^*ye)oAU^k;gsW;tFzwO zm`aVSRF1P+oa%APam5p?PlfP}vka#k$9jm$aUr{cngDaQjP{RHj>{H$hEtC7F_o6( zG_F!PPW#6Vhj@fJd(i%I%=>P$7QkEX)7R2qjvjJ@&+~nXv2Ct*ZOVQ*DSPL1at)pv zoA5Z}YcX9f=emLUp-_%vU1rt+vs#?$ah~Cn0m?2^ygA-9uPgsF}0&EXKB97q1QwHL^6%5grXQaMgJ zPB|_L1Mf5EAal)kqF_{y<2&Oc<+y3)>loGJl;h$j$!}JRQ$5ZzoN`>A;gsXrA=|+` zP^ccK92W-O4cXnC52%0Wx>u#aH1Bki)LKpbpxgAzG?>7?RHky;6<8zB{F>}$EW;_s z-5%mK&P(6cn7@P%@m zWjN(H<+w^lodA~Ml;g@FT*Em5)#H@o;x(KP)Z&!ml;gsiTo=p~{Q}8O?jg))E-dC; zL4338t!Iuk8f#rB^52nM?&1z(_z|}CS%y=Ne|yQjV)phcl|j@m--D$2v{a12AK2 zoFikcJTt>w9W#5MS$l%>2Gt#IXfylqU~r{tToJKuRK&RTaxU9JeHO}b9FudN;Z%>a z`!m(!l;cvyPcknbp5Ztzl;iUC^i+>)Gv3;+6UuSQamsPwjbYY0hh;eBxIDut$9aZR zj^qBpGMrI8PB|{5?4i@ig~vH3(4Y=$CO&e#YuU#NW82)|^W;|?J>))pEn*)Z`qx{o z*k&&tScX%MW3DWfBSBJ!#Q;rK=YH>#OIOVv?a_%YTy3nF7Yc4Pj z)U4KL%)#6l-V=PO*{-PYG9H)AmXE^1!PADC4s>dT#ao zEXyg!rD6G7X*l(+tDU2chUKiEXIh!N`fM6ZmHSZBYq$?yNrRbw%JtaK$EY4hEpn%F zoYmq~k4y6mryR!|1)g=8j5+p3Igb4Hbw9(Y9{0cJgT_^=9%orjIZipQ@|b5hvNhs!zst*bK_KxQ#~$g^F0gI;~3ku z!ZV!eamsO}N77&{!zsrp$9-^^`WcktxTkzD3dw4x99Is#Mch|jq&9%;kPB0+Cut5c z=Gg3QyN`KAGM{IrsH||sTRS1Qo>!clPmm= zd9WxRae?`=CiyAZ)%=Y7ig3Z5xgiZE+~-E0OM|ftryS?CIMw5ne$}^mDoM$-YIL~m(ah~Cn z<2=JD$3=W+I?Hg%aXkOLNKF8(lP-RaeRWV=;*uAr$s(*`%rTO~!@2kpb85}?JR?E2 z*4da!jjL3S+rJ|U#xk68oN`?2B=hl6y67y!DaUz+Q;zctr+S=n+~9-Ei-hWN5w%F= zxXP`J?SkrY5n~mU<0_9uJo8kJtFA~H$CPpp<&@)C_vuUSF&DAc0&2`7HpM$#?|$m9 z=22JOMMlHqZa2Os3a0wBvs#?$ah~Cn<5;gsV%!zss6J8V14aLRFH`f<1S#gzJ4N-fP5 zS90Hp-se0kMy2XP|DQ^gYb|=8yW&dnFI11?xY@o$%5l{9J;SLU=NZnjoN`>s+z!uh z%5k3Il;f1+=DZ%UHm7o2WjXg1M)f$>?NyE|uIIiIs>d<5Ygjq1bbxVPP>y45*|$^H z9C6BV(aRD1N0Sys;fTDuQ9&IP3}&q$?|)#(j`C(m%oac$Pz=m{4Em zy33d&fRXvGcA*?hcC0Vr70GtyZJHCz=R~8z{-@K=JzrERVSCc!@9nx>~e|iRbzYBEEvu;Zekxrv{)C| zgh@AV9-kKjMVH*d@j~+sH^^}@U5=5d-t9^;&*(6=w(onqBAest6Xjr%pZ8tIE5ggn zb2VS_-cZ=beKkhUx!xZ*P8eTIUd692-;Nc$v{nZvO`AxR@Qky=P$> zOzXF_1F|>zw()8XvS)3M{eKQ(TiLzAD_XyGdlp9g96tLBw|@gQUyN>Ym3ukgkZ_Dl zbBmi9j(FdkTQ|D##f*bS?+?_EF?!Aw_OWg=!dJAHd6~V3kX%Q*nxDJ+1m_U4Iplqe zeXnmVuPDW?dN;=aU5=3%yvH@~;P@fA#SIiw+Me3fJQpTAoEsdgBd&21=P|+p+6xJL z{hG=y?sbs7uFEU3^|la9m7_V`SOz{TtdWoG};bxGGHU6=ftr0bHdOS)gu{gUpNbied} H+%NqPHAu^@ literal 0 HcmV?d00001 diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 6f6213b1e26..d6eddef01df 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -5738,9 +5738,42 @@ static void check_sample_(int line, IMFSample *sample, const void *expect_buf, H ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret); } +#define check_sample_pcm16(a, b, c, d) check_sample_pcm16_(__LINE__, a, b, c, d) +static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file, BOOL todo) +{ + IMFMediaBuffer *media_buffer; + DWORD i, length; + BYTE *buffer; + HRESULT hr; + ULONG ret; + + hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer); + ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr); + hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length); + ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr); + + /* check that buffer values are close enough, there's some differences in + * the output of audio DSP between 32bit and 64bit implementation + */ + for (i = 0; i < length; i += 2) + { + DWORD expect = *(INT16 *)(expect_buf + i), value = *(INT16 *)(buffer + i); + if (expect - value + 512 > 1024) break; + } + + todo_wine_if(todo) + ok_(__FILE__, line)(i == length, "unexpected buffer data\n"); + + if (output_file) WriteFile(output_file, buffer, length, &length, NULL); + hr = IMFMediaBuffer_Unlock(media_buffer); + ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr); + ret = IMFMediaBuffer_Release(media_buffer); + ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret); +} + static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0}; -static const BYTE wma_decoded_data[0x4000] = {0}; -static const ULONG wma_block_size = 1487; +static const ULONG wmaenc_block_size = 1487; +static const ULONG wmadec_block_size = 0x2000; static void test_wma_encoder(void) { @@ -5789,19 +5822,19 @@ static void test_wma_encoder(void) ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050), ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003), - ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wma_block_size), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size), ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)), {0}, }; MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8}; MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float}; + ULONG audio_data_len, wmaenc_data_len; + const BYTE *audio_data, *wmaenc_data; MFT_OUTPUT_STREAM_INFO output_info; MFT_INPUT_STREAM_INFO input_info; MFT_OUTPUT_DATA_BUFFER output; - const BYTE *wma_encoded_data; WCHAR output_path[MAX_PATH]; - ULONG wma_encoded_data_len; IMFMediaType *media_type; IMFTransform *transform; DWORD status, length; @@ -5847,39 +5880,42 @@ static void test_wma_encoder(void) hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags); - ok(output_info.cbSize == wma_block_size, "got cbSize %#lx\n", output_info.cbSize); + ok(output_info.cbSize == wmaenc_block_size, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment); - i = 0; - sample = create_sample(wma_decoded_data, sizeof(wma_decoded_data)); - while (SUCCEEDED(hr = IMFTransform_ProcessInput(transform, 0, sample, 0))) - { - ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); - i += sizeof(wma_decoded_data); - } - ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); - ok(i == 0x204000, "ProcessInput consumed %#lx bytes\n", i); + resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA); + ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError()); + audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); + audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource); + ok(audio_data_len == 179928, "got length %lu\n", audio_data_len); + sample = create_sample(audio_data, audio_data_len); + hr = IMFSample_SetSampleTime(sample, 0); + ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr); + hr = IMFSample_SetSampleDuration(sample, 10000000); + ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr); + hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0); ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); + IMFSample_Release(sample); status = 0xdeadbeef; sample = create_sample(NULL, output_info.cbSize); memset(&output, 0, sizeof(output)); output.pSample = sample; - /* check wmadata.bin against current encoder output */ - resource = FindResourceW(NULL, L"wmadata.bin", (const WCHAR *)RT_RCDATA); + resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA); ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError()); - wma_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); - wma_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource); - ok(wma_encoded_data_len % wma_block_size == 0, "got wma encoded length %lu\n", wma_encoded_data_len); + wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); + wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource); + ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len); /* and generate a new one as well in a temporary directory */ GetTempPathW(ARRAY_SIZE(output_path), output_path); - lstrcatW(output_path, L"wmadata.bin"); + lstrcatW(output_path, L"wmaencdata.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 %lu\n", GetLastError()); @@ -5890,14 +5926,14 @@ static void test_wma_encoder(void) ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || - broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|5)) /* win7 */, + broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* win7 */, "got dwStatus %#lx\n", output.dwStatus); ok(status == 0, "got status %#lx\n", status); - ok(wma_encoded_data_len > i * wma_block_size, "got %lu blocks\n", i); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); - ok(length == wma_block_size, "got length %lu\n", length); - check_sample(sample, wma_encoded_data + i * wma_block_size, output_file); + ok(length == wmaenc_block_size, "got length %lu\n", length); + ok(wmaenc_data_len > i * wmaenc_block_size, "got %lu blocks\n", i); + check_sample(sample, wmaenc_data + i * wmaenc_block_size, output_file); winetest_pop_context(); i++; } @@ -6019,7 +6055,7 @@ static void test_wma_decoder(void) ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8), ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)), - ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wma_block_size), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size), ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), {0}, @@ -6027,26 +6063,28 @@ static void test_wma_decoder(void) static const struct attribute_desc output_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), - ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), - ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400), - ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050), - ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4), {0}, }; MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8}; MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float}; + ULONG wmadec_data_len, wmaenc_data_len; + const BYTE *wmadec_data, *wmaenc_data; MFT_OUTPUT_STREAM_INFO output_info; MFT_OUTPUT_DATA_BUFFER outputs[2]; MFT_INPUT_STREAM_INFO input_info; MFT_OUTPUT_DATA_BUFFER output; - const BYTE *wma_encoded_data; - ULONG wma_encoded_data_len; + WCHAR output_path[MAX_PATH]; IMFMediaType *media_type; IMFTransform *transform; DWORD status, length; + HANDLE output_file; IMFSample *sample; HRSRC resource; GUID class_id; @@ -6166,7 +6204,7 @@ static void test_wma_decoder(void) ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr); ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags); - ok(input_info.cbSize == wma_block_size, "got cbSize %lu\n", input_info.cbSize); + ok(input_info.cbSize == wmaenc_block_size, "got cbSize %lu\n", input_info.cbSize); ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead); ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment); @@ -6201,27 +6239,26 @@ static void test_wma_decoder(void) hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags); - ok(output_info.cbSize == sizeof(wma_decoded_data), "got cbSize %#lx\n", output_info.cbSize); + ok(output_info.cbSize == wmadec_block_size, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment); - /* resource is generated using test_wma_encoder output file */ - resource = FindResourceW(NULL, L"wmadata.bin", (const WCHAR *)RT_RCDATA); + resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA); ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError()); - wma_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); - wma_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource); - ok(wma_encoded_data_len % wma_block_size == 0, "got wma encoded length %lu\n", wma_encoded_data_len); + wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); + wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource); + ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len); - sample = create_sample(wma_encoded_data, wma_block_size / 2); + sample = create_sample(wmaenc_data, wmaenc_block_size / 2); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); - sample = create_sample(wma_encoded_data, wma_block_size + 1); + sample = create_sample(wmaenc_data, wmaenc_block_size + 1); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); - sample = create_sample(wma_encoded_data, wma_block_size); + sample = create_sample(wmaenc_data, wmaenc_block_size); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); @@ -6245,7 +6282,7 @@ static void test_wma_decoder(void) ok(!output.pEvents, "got pEvents %p\n", output.pEvents); ok(status == 0, "got status %#lx\n", status); - sample = create_sample(wma_encoded_data, wma_block_size); + sample = create_sample(wmaenc_data, wmaenc_block_size); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); @@ -6263,7 +6300,7 @@ static void test_wma_decoder(void) status = 0xdeadbeef; memset(&output, 0, sizeof(output)); - output_info.cbSize = sizeof(wma_decoded_data); + output_info.cbSize = wmadec_block_size; sample = create_sample(NULL, output_info.cbSize); outputs[0].pSample = sample; sample = create_sample(NULL, output_info.cbSize); @@ -6273,18 +6310,30 @@ static void test_wma_decoder(void) IMFSample_Release(outputs[0].pSample); IMFSample_Release(outputs[1].pSample); + resource = FindResourceW(NULL, L"wmadecdata.bin", (const WCHAR *)RT_RCDATA); + ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError()); + wmadec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); + wmadec_data_len = SizeofResource(GetModuleHandleW(NULL), resource); + ok(wmadec_data_len == wmadec_block_size * 7 / 2, "got length %lu\n", wmadec_data_len); + + /* and generate a new one as well in a temporary directory */ + GetTempPathW(ARRAY_SIZE(output_path), output_path); + lstrcatW(output_path, L"wmadecdata.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 %lu\n", GetLastError()); + status = 0xdeadbeef; - output_info.cbSize = sizeof(wma_decoded_data); + output_info.cbSize = wmadec_block_size; sample = create_sample(NULL, output_info.cbSize); memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); - ok(output.pSample == sample, "got pSample %p\n", output.pSample); - i = 0; - while (hr == S_OK) + for (i = 0; i < 4; ++i) { + winetest_push_context("%lu", i); + + ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 || broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */, @@ -6295,20 +6344,21 @@ static void test_wma_decoder(void) if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7))) { - ok(length == sizeof(wma_decoded_data), "got length %lu\n", length); - check_sample(sample, wma_decoded_data, NULL); - i += sizeof(wma_decoded_data); + ok(length == wmadec_block_size, "got length %lu\n", length); + check_sample_pcm16(sample, wmadec_data, output_file, TRUE); + wmadec_data += wmadec_block_size; + wmadec_data_len -= wmadec_block_size; } else { /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */ todo_wine - ok(length == sizeof(wma_decoded_data) / 2, "got length %lu\n", length); - if (length == sizeof(wma_decoded_data) / 2) - { - check_sample(sample, wma_decoded_data, NULL); - i += sizeof(wma_decoded_data) / 2; - } + ok(length == wmadec_block_size / 2, "got length %lu\n", length); + + if (length == wmadec_block_size / 2) + check_sample_pcm16(sample, wmadec_data, output_file, FALSE); + wmadec_data += length; + wmadec_data_len -= length; } ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); @@ -6318,9 +6368,14 @@ static void test_wma_decoder(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + + winetest_pop_context(); } todo_wine - ok(i == 0xe000, "ProcessOutput produced %#lx bytes\n", i); + ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len); + + trace("created %s\n", debugstr_w(output_path)); + CloseHandle(output_file); ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); @@ -6346,7 +6401,7 @@ static void test_wma_decoder(void) ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); - sample = create_sample(wma_encoded_data, wma_block_size); + sample = create_sample(wmaenc_data, wmaenc_block_size); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index 5a2bf913672..483ff53ca94 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -20,8 +20,14 @@ #include "windef.h" -/* @makedep: wmadata.bin */ -wmadata.bin RCDATA wmadata.bin +/* @makedep: audiodata.bin */ +audiodata.bin RCDATA audiodata.bin + +/* @makedep: wmaencdata.bin */ +wmaencdata.bin RCDATA wmaencdata.bin + +/* @makedep: wmadecdata.bin */ +wmadecdata.bin RCDATA wmadecdata.bin /* @makedep: h264data.bin */ h264data.bin RCDATA h264data.bin diff --git a/dlls/mf/tests/wmadata.bin b/dlls/mf/tests/wmadata.bin deleted file mode 100644 index 6c70c14ce3208f5c711effe156ac484c706686cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49071 zcmeI%v1tQA5CzZ!Co(v2sMN-RN>FHQ2Zt+A0S?rGRe*vkK_#dJm7ofYN{~8G=;V@t zY2d@#Y&QD5fzQG|4#V$leA<6a-|s)KZ=Zi3&-<6f;1D1{fIybOau^hN*2<(MK!89e zuu|t8i#q}Y2&4(D)p^>=`wC6loV)}G5GVp$uk+$z zAV7dXsK8F0hi*=60t5&Yfk~Yg4+8-L1VRN4>O6FFViO=hpa>l2I`6YKBS3&an!rV!r>#t00t5(j0#|k3vA82ZfIynSeXes~p=q0w zmjD3*MPT7|UOWs02oMMrSgP~T&52Eb0D&T~Qs>3PK!5;&P=U2N58a&D1PBl)0^?lg zzCsI&fdBylX#yLs^R$)8OMn1@PGGCfI~I2Y2oOjU*s1fhmB~wh0D(?mQs*6uI|2j< zqzN46I`R diff --git a/dlls/mf/tests/wmadecdata.bin b/dlls/mf/tests/wmadecdata.bin new file mode 100644 index 0000000000000000000000000000000000000000..4e339804f1f908f4b73c61ef275da893022da2b6 GIT binary patch literal 28672 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 Sw4N#Oaqn9@p`Br?_xL9hNbigQ literal 0 HcmV?d00001