From dd24dfa8b1db35afc66f188999c89d1e7b3ca18f Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Mon, 27 Oct 2025 12:27:17 -0700 Subject: [PATCH 01/14] Decoder-native resize public implementation --- src/torchcodec/_core/Transform.cpp | 2 +- src/torchcodec/decoders/_video_decoder.py | 22 ++++++- test/generate_reference_resources.py | 10 +++ ..._135_flags_bilinear.stream3.frame000017.pt | Bin 0 -> 98868 bytes ..._135_flags_bilinear.stream3.frame000230.pt | Bin 0 -> 98868 bytes ..._135_flags_bilinear.stream3.frame000389.pt | Bin 0 -> 98868 bytes test/test_transform_ops.py | 58 +++++++++++++++++- test/utils.py | 2 +- 8 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000017.pt create mode 100644 test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000230.pt create mode 100644 test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000389.pt diff --git a/src/torchcodec/_core/Transform.cpp b/src/torchcodec/_core/Transform.cpp index 6083986e1..aa1c2d2e7 100644 --- a/src/torchcodec/_core/Transform.cpp +++ b/src/torchcodec/_core/Transform.cpp @@ -42,7 +42,7 @@ int toSwsInterpolation(ResizeTransform::InterpolationMode mode) { std::string ResizeTransform::getFilterGraphCpu() const { return "scale=" + std::to_string(outputDims_.width) + ":" + std::to_string(outputDims_.height) + - ":sws_flags=" + toFilterGraphInterpolation(interpolationMode_); + ":flags=" + toFilterGraphInterpolation(interpolationMode_); } std::optional ResizeTransform::getOutputFrameDims() const { diff --git a/src/torchcodec/decoders/_video_decoder.py b/src/torchcodec/decoders/_video_decoder.py index 130927c2e..5917abed2 100644 --- a/src/torchcodec/decoders/_video_decoder.py +++ b/src/torchcodec/decoders/_video_decoder.py @@ -8,7 +8,7 @@ import json import numbers from pathlib import Path -from typing import Literal, Optional, Tuple, Union +from typing import Any, List, Literal, Optional, Tuple, Union import torch from torch import device as torch_device, Tensor @@ -103,6 +103,7 @@ def __init__( dimension_order: Literal["NCHW", "NHWC"] = "NCHW", num_ffmpeg_threads: int = 1, device: Optional[Union[str, torch_device]] = "cpu", + transforms: List[Any] = [], # TRANSFORMS TODO: what is the user-facing type? seek_mode: Literal["exact", "approximate"] = "exact", custom_frame_mappings: Optional[ Union[str, bytes, io.RawIOBase, io.BufferedReader] @@ -148,6 +149,8 @@ def __init__( device_variant = _get_cuda_backend() + transform_specs = make_transform_specs(transforms) + core.add_video_stream( self._decoder, stream_index=stream_index, @@ -155,6 +158,7 @@ def __init__( num_threads=num_ffmpeg_threads, device=device, device_variant=device_variant, + transform_specs=transform_specs, custom_frame_mappings=custom_frame_mappings_data, ) @@ -431,6 +435,22 @@ def _get_and_validate_stream_metadata( num_frames, ) +def make_transform_specs(transforms: List[Any]) -> str: + from torchvision.transforms import v2 + + transform_specs = [] + for transform in transforms: + if isinstance(transform, v2.Resize): + if len(transform.size) != 2: + raise ValueError( + f"Resize transform must have a (height, width) pair for the size, got {transform.size}." + ) + transform_specs.append(f"resize, {transform.size[0]}, {transform.size[1]}") + else: + raise ValueError( + f"Unsupported transform {transform}." + ) + return ";".join(transform_specs) def _read_custom_frame_mappings( custom_frame_mappings: Union[str, bytes, io.RawIOBase, io.BufferedReader] diff --git a/test/generate_reference_resources.py b/test/generate_reference_resources.py index 953fb996e..e02ae9d88 100644 --- a/test/generate_reference_resources.py +++ b/test/generate_reference_resources.py @@ -123,6 +123,16 @@ def generate_nasa_13013_references(): NASA_VIDEO, frame_index=frame, stream_index=3, filters=crop_filter ) + frames = [17, 230, 389] + # Note that the resize algorithm passed to flags is exposed to users, + # but bilinear is the default we use. + resize_filter = "scale=240:135:flags=bilinear" + for frame in frames: + generate_frame_by_index( + NASA_VIDEO, frame_index=frame, stream_index=3, filters=resize_filter + ) + + def generate_h265_video_references(): # This video was generated by running the following: diff --git a/test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000017.pt b/test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000017.pt new file mode 100644 index 0000000000000000000000000000000000000000..5da3e81fefc7e4189986382fd9305fb447134b3f GIT binary patch literal 98868 zcmeFa_nREodFMObU7;&+8L~!Oy+Bd%Zv1`zPG*Ij5_-dN2ck6tyNu;(67o84QLq z-Jkx}_q^|W-m_)F!F6;vogKIRneT{pTsU&&$f2IT?w-ER2OjM2ymIWw`4fkF`@8YE zfkP+HA31g9(9tvJ&s;ch=evTh zJaX#9B^&!E^2{SwPi$kKlP}qK+wdjbmmIqt`2S-MUc1Dt|K4M^j;ojWtqUCsHy8fD z1;@=x!p2|P7aR+=o0r6wjvc#r{``q!SI=C$a7EsH`S^*;CyuWGu--+z7QXAT0Z(eo)zcT zb8ArDf*DjV2Qxmo(raqMOnCV9^UPod!#2TV^33xd3Nrx}B;%Un-MpaT(JnN@Ap&d) zvmN&>U@rn=lVtqx4vzlq?Z1LUTIqMk=a+>UpS=A^Zhq!doLqRn{RS)cK8e2`c1(|=<;19#!sG|%mRV`ZLOo|%#im`Pa7YTLDy zjkfC*xb1N0mVlSm5Y#h+VLuD7>Tv2do>JQ3?yzfi&cliR_GlsvJttnsj$4n|VTVt4 zcff>G(_#~vJ{<0)?dRv*HX0qAo4#|G(PtoSv%`t;EUez+t~`H=w87>F`Tu`io|)-o zk1J_!`{%7ZlWQn52_nlap5cu<98g+-iof-7Vvu)+ED@w^L(laNJAkKV!!Fw#ZX)uc z-{A}(%x_4(IdL)?!iJ!$PU8``p62SnyfGOUP0o$?KJX@ChlMu7Sf>!k+y8u!*YeYU z)6voPELxvldcD$m(0GlOW;TqMlBo2(=(9lu)z}p^*_zX66zQf#w{toT;O#PbwqDTZ zp{3i_rwcq=qb1jEuLSwvQ#?PwGtl-d-ZRfE1Hc}U(Q1WZp2-VJoyML0#vOSkUV_H5 zJVSViVYUlC2T^9oX%Jx(0ycOOLMh%O9>6Th5f(sNbRvR+7=V$s+ub&NnGOF5Pzw7I zz!z{*#NkAQX@oc_#0V!IM(~(nvTftt7GK>;#XM6TJ>-u6l~KllJI=qKu*wA5fJ zx_DL*{F0!?Z`rg4%?22GEt6+*mp7JpHcoBX&bE6ryJZ7NxP{j3`!-(znML@ThMDtp zknpvF_jmAqyU-+=!QA2ScG%z|@Re{5K|u}+a)g&7hC~MiNG|+?-EFsFwFsEKHXa58 z=tejx$`Pc)9Oao_2RVs^!)clsze9xmpl>CbPHE-+IK^%RQX+N^?`RrE0)(lw-OgL} z*}Ps3=T9YinRjQ~6SWj$vw+f0GP25u4lK{HHou+c7R-=n6J}fxo-Ig&ZHBZdXy!%J z_cHfOA1w<#mBxuw!eUZ781M?2ANFyn(IPgm>17SDDY)-28VfIQ!Zw23h;*j*buEJ3=B z=Voe-n1Pk_*@PJvuo+F5q0d|sWsGDtSn0~gDQGvxYi`h2@eQ(wWTX1QN>%eErjLYFYiJhK5aKGUwxHXcyH zO-n z5LQvv*nGKsJx_YM@J%v;!uVy$k#dyYr5k$95(QcWLHmZR%3O6KhL2@8Q4ZZzB zwHxJ_yYjpgY2$Un|65+wPvWKJnXp{`x_LGhgXXHRdC{JWqhL2HdMhA(n?5s%hG(WQ zGoJB?)f^FLE?^fRo3P3;)stN{u_Y9(0c>6l^Smz{NUd8n*V|YX38eF}#Oj{zvzs;y z7Yp-UU0s=);L34IhEviAhmvUq0lS4X95^Q%z8Z^1gKC@8-(duhHs#vn*&%AEKe8a1 z5USFa6^B(uT6w&dEwsFJpJb%lp9afEzbem5#ThS6n?Bzg&s45;B-UCm!%mo1d0D?< z@C=5{0Nd1NcwwPwb|T8lFXV$Uaf#<_+-xQR6KKo)AOUViC{)m{Xu`+?~5vm zHxY_uV->-br91=a46kN67Oph!N>i;S?wTX+8s9uhz%~|)4k=`l0(a$^bGi}e5&_jf z+WK@^t(~Ji@3CwW?~|y@^mn!p+k+MS((4p5Wy&G0-k~|q$Xt)kh%|fgBRuH5i@|0@g zuIb`2!4axS*yXTY4gzTw#CsU6eUN1qwCjoRY$6RWP3$yn+v6Ng2Mdz%;Fm#q$*cDX z1G@Fw-^ML_zqjgr%O~Q9VK#g+TZ5Yb<3h31mP^usi2__Rn#~NXrNNp{Ug>%%(srcI zZVyVhopDZ579?oGxq}ao3-TEai$t3kwM$7(CT;-%EO~bvnGKI8BZ@(YGi zf@jSgcQ}1cXArgo-ndfgJFs?7FjAIXalxIE+*!e$=d@-}m>JS(2Mjg~1x~w}2|PffNV9M_uo6dVx-C0xv$fU1KT$ZhV8+#* zd2V)rwk`L}rQfnVQxR4{G7Bq{D{;Hx=a;DTGBCH}O_Z6yOp(y1$Tx8H6B;%52Gv-f;x<83d87lx2bdjBk3;eho+XW!G|q`| zqi2-`t(-R3(Ux^0UX)fp-m=TXPYBib%5&@Kx>ueJ%l9Gi3|(F7It&xCEZa+XW-wz7 z2=5`m*;1EFt*_|L!vNcyBz@=L{Tz?lw*;3fxsusbZFT2JHkyw_${~N*q2(P~(Wzxq ziOxc#N{Zm_qzWT#;aSwOW;9JTtTk4Su+ub{P*bEyIR?Jk=>0&>&9@b}??FRdRG9*}%L_0cNtN z7)x{=8JpTYGdDFl8;ewJo+780oq9>~1Kxs`gGBRM0b#<7io z=sUu9ApgXUv{=aIgo(uhjU*)i7_|fm0=%7mLnt%qEOwvGu2G&#zEJ1knT@l(tLBI2 z5~(iUlachiQ!6_3wCX8|YQoNkooddh6@!**RMfx6i#vT(Rvq$PCgw;4vW?-ylNzg0=0H$vcv^fPS;VC;h zpB>m*6_nf=x4*h;a>K6GTQ{%X9!}Q1o{ZO>QMH0y%cy$U?JIF&jCZC0Eg*MlB}prZ zo)QGyso^sjSxZB`MPjP+Ev@jJrHQG}d|MPezPT>9W zOcEVTc!@IGB`g5ReV?S))GUOWcxLhjAtgdy$q)`*8G-Xkye5l&8A)kZ;?RbJhu7^( z#u`pN>31bVE;M!Iot~Vc7d*kLtmW){9HxZ=OjKIZONyRXU1VJ;xuUX;Z%YK6sWf}! z-5Ji6aHxnjQ;nMff|T9mkf4MSjB2PfFZmeHW~rrF5I3wHN#eB{mOkZ~y@$=lIfwNP zZs8d>HM1)Q7x&1sn`FSqZljiGzBj+o(r3c6A<-}rZI+|WZy0tO`b_(oA-^^;=8#eZ zW*H=dXI!K@#3)kJw0R@KscENPmb_I}%jt4BXwz3NCMncP2zNExA)p7a}RUQ;IvOC?VvlVTs9SG|&!TU4V?U5MZqd z(rM0>Q(T}dn>x0Ers*_ z`G((@=C~l^4aQgNr9YC@2r;9rn} zk{pzsei1FE&H%`i+-b;o%U~0;-2~g98eqc+F{(*-ACGVmo*B|mX;BWqNE@z$WbjZr zq)F+fmu{w`TM}*c8+P(qcYF+cIhMjqe$AF9H+gPz7mR9a#iXgp(1doLExloFI^5!R zB~5<6JTtrv`(b!#g0#sqE?_p$bx$hVyp$D{yi+X@q@^(aIjwgSm|<%LPgV5Ro!%Pf zuex1{u4Hwn(5b31jz=-ki-x)zdrpp4CM6;06ax}K6@9!A6eTbg1;etMaKTh4amF*= zrw-oZz#EqCPed*b%SOgCwb{&*z-$w_Zs!?74V5N56Qm8E8PcK>q)5}{p()g)$kLpR zfQq3-qIqlozxfh>4Aj{AD=Y)^?L037Gs$UKY{rMrv$=BS2AY?bSF<6+^Mz#Qb9 zC}$@H$}^C5h-o_tg?4o41@Kpbs~~!+ytl^t>rP*t@T|r=6Xi<0jMbSgy!G^LGX*b&nZBM!}uqf*5sK(Rh_i|Fa^jp ziwMedmbwn6&n=#LSFDX^VmyKfn)L8tdB_Sbyg($HskGVuPhTmT>!2^CHP>N<;eNkf z9_A%HFAwvF%d=@eEV|v?%7-#pvr^Us`vdaqMGl$R4D5t*rZ_1jNEs34SxnjNG2}XI z9M)MWSu0AOn$y=Q`05DoEck2jczv+gQ%crtQp_eMc`1|*CQhwezrJrmcLhWg=|qha zJQ70mD4b7o2EyKiEJsK#8qKI^5h06K(lJHArdtN+Pm*v*aT~U@C^1pXNS?ez9CcpQ za@0!`JI(Sfl;oJ;j*D7MayLVOnRkUamGK+^&j@&FK}4MegPWM~kW8fQ4(Ja-8VeuO zNJFLXcZSWMe?^$@#IZri_ z=&EEJemw?l_iCZJRRf2%%$?Y@dC&CvwY@!VIRZ*KWIuSHB}nIgLW zIBZ%(R**v;2EQztmyn~t4-n!Y<|uZfXG4I)3BXH8S{gYJlA~tpM4He;mE1r&fwH5h zB_tHzX$Wp&KY%ooXig>)O?Y-{CeIv?t??$(WW)h`?LK}y-wEdT$un&jFcO|*o|VNj zTd!B-c^Q~L1fET#n`=X8BYGjwL_~N-FDU*Kr2J?1cL-=mPK!ts>zz)7uK}K^K6i@n z&stgc=0cu0DsgZZYkE6xp51cm+McWXb{&}Ac;(=xR4R*sGj>7aIk(s8U0uw-cxe4^ zJ#+ZcQ+s^Aq|L57ApVY^osT;Bm>{B15)0~ycreKcXo8}N7hXfBC>Dumx0bvGr(R^y z%zlt$b&3VjgR<5PXf;Ke@=RSvOQM}Rk6Q-m?jT-zx&187R;7=JKHmlA`;%wjYD#p= zKa&L@)oL5&ZfSOc6A@>-7`35LZui=`7^fi5fO<#WsdtN>9%?q4Ji~7QX{Q|XC_z;T z$-KUOtow@>H@nt`}pgp*DVb9 z^SsV?pm^uO@=$gqv7#)c%iWn=XRe?s$iraIFWL*;9Z2{H0p#~&9}Evl=lFRj)yR7w zQ>`O&NJ8?Y6rBX9W;_FFQEf^zPb8XTq;MtVUnQ{qHwc zh8YQ*X5fC*9K5r%ZbC8}OZQ% zO6nwJ5AcpVH5l)hsD>>_lMJ4bk=D)5e_Cg0?hS9P4M8>G`TkDXt;DnGsg_*OJO;5| zEZb~JYqWA2X7eZ7agBvMnP+9@;^+)RHy-I{SUwr6JmQcsLCX>*+im62W4nv|*s}BzWow-rGP32;wxlX^;!i zUsHTFP6#?MeZUiodLv%9Hc^iqTHSeZ!}!L&v4gX-?_Ah;Y18;ZCG*_s;-Q|{VpnwA zaQ@2T(9J`WU%9k!cE`Nm6?E9Oh%bD4!_<#HbNy$(@$^r={KW6Se(h^do?bIF#yKJm zq{PXrFg#s;q)^baBzX$5w;+2e5(+vr@4+5rZx)^efnAMMr4y1C#|qKuY9Y;dW=J!h z*=82j`A=6mY!@vgn(=HmmsI!T#rx&il9VHRv@IVJo{g1Yv)2fXF(%Jsj1?P`LWhA9 zJJ-f@lUNJPY!)0t8hvHJwfQx-!^}Rzc1ztG&jc8fVWuNukY2F6itxr(o|{zP#xwdw zp>K^;sVA39#FN*KZr?dGwWhnep+2&Aa`Menv(M~XyS1luajbG-G;w92@8a(Hy_0?W zr|Pd?+WO4tP3s3bdkXo7w$Hr#;QUV>-|~|iM}KM%>pXTj0cv7P8TU1vQoGpH`CFa6LrJZ<}A{))NE^{%XYTo z9&=GTKDj&tW@f|iXn`5e&##4N6X_3+XOM%TUZ@6U05h*w?#i?5tJ#sA;FVSN>Oz0r zrw6X?ntShw(_ec0)UKKN@mk}`hQ60hZ@#{5a=x6sG?9I9Ed9mfvtPZu*v+%_QGNpRu#g=xJZZY#90+fkeL_ea3$p zhBGI*i-7rdo|pIyB%ht$Dw^wX%U<2rIJjoeU!tc>Tf@JV$Z^czHDXl+NoW0 zgD2LH)YG|b_4v`w@QwAgFPvEW#j87SUR-?c?Di-2u0Obbc-K_-gB$ujb7<`C3p3w; za`Dfe-Sx9)_x<#_BY%GL+~%=i4t*?eM3iTn7)Fkc=`(2{vG@(emskBpcr%7Xr{FrA zF8p3ZqD58*XGk|&J7A5|%?~XGqm^)`LQPIjV8Qg6@a$lonUqBw zf~7b@7;ep>HI2lQ3#<2_176rj!wBzOKG2!TVUKpxJd^(%Y_k~z4}@9oMw>K`wt2Kk zltm3N*AP~HrZ8LmGs!}W-in>W@1mBnnW0L~EvfU}rQbR;^PLyZEzYj#NtUnf-}w6F zT~~H)8m<+S!O)gc_(Wg)l|w_Hzr6kVW3#WFT>XV}3vXRs{OZH|Z=P6uaLeqGHGLP> z54>@B;@ztofAQLpfBMRWcON?#^QSNeugSB3tTI-7CE0^*0?phVF0evWd_`BF><(5` ze@XQf73w|EF@iiET!%=IjxOQZTpMy!qCZahdOz`b|LJL(Q;f844xUxcr=_dU~cCbi$Qk*X=+LJ9^5p4Y}1;k*H?&ypF6VlcV0Yu zWW#JGkl8t0zj3!wePX5Ltj2Vx6o4+cv*2O6P41r#p(T%_49Mx&+nQ1#$gxxN44^^-q;{eho-?#dtBJo|-0Tw>d#6IMl-JJd0GH4YR={x|8$N9cWDQ zRwV2kv1{pM>ZJqg-#meyjh9+*45x?58< z&W`?3{luEull#`3UN^pH)xfdY!DkLnfBxe9x1ZSY=g;r|o7WEi%`1og`R$AU@{Mc% z^zFwU-hV(8V@-V~+i!!U`wl#Nv0QCg4#+jCEg%^@L!w>8b>t0+Mmicb#H7;|m(&P& zW=NB6QkssY3qw*~vDQ}bB7Pirw)BFUCK(r&{(RDFWQNs0Q&~2*xRPZurMlVV%qCN@ zK~-dG1cLevqdlXQXEs5_MSJd|<&(|L&SZb+3T)H*HCYnEvCvf^8A;c{v5^{V6BazP z4?RDEn&;J`O)Vfz$6GQR5NENOc4j1#<_*r*u)E4=6G90?LYIY2F6XmfIK1(j=e8c3 zT@~>JUO2z|d(WQuw~rm{%$Gu1bgsAS_?phA_m5rMG}M`jW3&j*sT0Nct=;{fJG%DO zV_RN0vH6kRGp9FB9-bY(zNP=m=jVU=(vg4u+C%^Sn~(nE+gEqb%{llm)`Mh8XxDhb zFT0|Ww}@_42`OkxfM;N=QJ#tA2o$hFl)Wgmpq+^p5Zwt30Fl&?Qwfo7QpG1A2+}0c z0f`3BupBJQidXhio-Ih5JU1IQevLe%E8albs@1pgjIB}(X*x89?2~Qs%v*T2X6lyX zx$f}Scy}=vig(u<0e=$3j$|VJ#IEVDonH6k-gSPD=irw0?_S;X?%A2aQY{@wT-~$z z%C6Om(|wx+$`@q(x53Ihv zb>yjS6K|Z_`2CybXGSN<0Rd#lzsqLFF>qc<4Wp3*rFJy?nLNwhDtK109t>51G#+uS z_=}1U#TVwHu}6R`46&ulNJnD}E%t_++gON18%ua(2yt!^@y|Arf@X0)RaBb(`9s!c z;xt%Yo9@aq4pjYc^_h&jZz8=C&s3$GxjVW5Y}4m^<{2to=e(VIpg29&y=UE6Dvs)ThgsWD~2Q;jn-&RBI6E_ z<)DcUQeLt0Om4mg5BFVR<=4P7%{d!QbgUYP)*4t2tKYzcH)=WFm){^`Rm>nw%PiUx zcUFD=U_8TYwEGR>Ivl<(3@YEUw)e#5sbn<8@!ridt8ZP{d1U?gKq>2zoW)%Jt#cc` zdT#6KnLb?&?;P#DxpVTN4Wm!*9J{f9ZmdzWV;8x@lMnhg4^+?0bl+G++IiC-y>$2& zZyf#kt;4@~<>=pj=G5PP{^DP~_3#@Ho%HyVNZNyB1QPYw7l0v4s-O9d8a6Nzn7uXC zUv~v6?qF35)rjRVB-+ZeSza;qc{!eG(;Yf{*{;t|0ME_ew7JW**{5MG2of7+VvG~b z5cIeNI&Tdfzvx;g*=Dw9ilynSJ{hBxnch;dwU$e;)1L(zJFy;QkNAR?ueM$<&oi+c z)Nimy>YrEAXDiR5zYBr>I&?lKW4SGTg`KN91KzMGc+TzH^%rkF^CxdT_tmG*l{0DC z8nUSBF<`{;R+(NQP)BZEsP+R0}^dbbbx1yG|DT?a*%HSran7;)Iy`MLL?d%`V-Ex z(W*gg^HQFTvp*=$1mnB#OvXxJet7scp5uZuf#91Y|LgF~`#TG%;@1A+)`618jUl4G zM~?0LyKlexkKcdeufFl(bbo)u7kpsvx}&orgSm=V^5>(m{o{qpn+KoWHuCJjnLTr> zBASnPNTO3aINkT#*LQy7^7h}oe(3E7_q}jp{lmLgU0ED?X7}Xxp5FhXFJIoXc9x`N zP<|pXdokcqb4UH2WWba1p!EoAJ%3U1SEN8)4mO%FhZ=gg6G)ppn~4ro3~A92J^!o% z-o`Vltf%oa(s;ahE<=f7@OB^JR2}miEi7Gy`nxZ$1^zuO-`~9q{P3L zKErRIrN5S|ZXPOc=`YD@*eUrhEv|m|(S3jM=C!~5=JSh_tJ2==m!3NH-Pg~)_`tz* zGN-!(gX!3KF1CHBbY<7fj;Vo4EXt!L!=Vo5lJA^d^Sy_+{_>?Ge{<`^k8d9Ri_e_; zlh-eO>$%h4efj*iUVUJ&+Jn1^m1p9gd5@|D{N9xANx8f^*k&bIlS7>v6=%TgiF8t= ziA2-d3Q61{7|*H)E}BU+hR+avCMgcm&Os&{m^`zsSZEAJ*C?&3+-HqR_wJwX!ZThe z({Ip(Gcz01Ik)i)l?KxH>Nm)_QP|+$49sD^7r()5Gp#U^_ED0xySv{&vAZgG8iEHq zP!OcyStQ+|cN!} zQ3p=&VL^sDx997af5rwq+zu2Bzb)F_CA(I3=rzvMK*a=sN;g{%NQxmb%5DfDHksd*dH<2ubbaylq$OHm~Xrvkpmc5~xkHFkxM3)|^ zQx}bn4)k^8RDV|Sp-Cxa=rh_mFc^W%2QvyQ$U-B(-Q0)O)Mu=cSh=CuYj=O-?r!JV z3NtZL#_T?N@jiHF4Rv%RxW){IsmbOLV}NbKj0-Eq)@u`HT-*!K9c?_rx39>v!{FJW zS18Y<0?2p<(t@{7^mRF0Ih!2gd)_8^KYNr@p~^E zIks`yEydP%=bzcowWAyR3Q-bO*9_EOKDl`P;Fd@B&OUKq-2*%3V<8M?lm&;RIwZ~I z87L;VkCacW8~yz8^}qkrp`U*4+Hb#j_0u1hv8T-ORhmWnB(&YGjSN_IA*MZ@jCShcmo(Y9ctsOkO zIQziHp{Mt)eq_&@Vm!~|xIiGyDM(i?te$@E%&rG_&hA(4*JYvT$?eA z;9m9FiAgVUr=0X?IJPn)La1@nl#^vb2+~%+@hk951`!}IH%35sYA#O4Alyl{or#~e)8of z-+cJQscj1jt9l~AILd<9pMvEEMla%saLh44$-9#7tfd-WZ!Q+ACzD-)aLpg@X8KGX zBVA32CgpGNTyO;l(ymrtG%2hYP0`JcJGLams_?$%xdk(>sDEZWw_UH`H`vXBADQjx%4Z;+m2~E<2j+kN%$^^9=FHcgIr7=F3oduKoGtAf ztxa@g`qL?w9Q65OTUL)8nC(3^haD^356t$i@2*OsJL2_4-AdjY*gn|#J5L_@_isM* z%WvHH>03|#rZQCGA*q`g7J`GP!5C;L^y!)^>9rMLxIppyq zbx+dm&G@3r^Q?!2Pax)Z@TDguyd8tGX%I&amB?z_=k$YHmV-btJv$ zO5CZ$s;S0{r>_6;tH1Hg$;&=>7>78RmScIIfiyV}f!Ibc<8Oix4(U2(&P5`Rcnv!nR$5s z+5>YFiBL+@L+d7oHw{#Fj~0$iRu4~h9hvM&`hvRK=aO7q$@Hs-*8Swsg+F_G@yD;7 z`|%ea`_X3~{kz|M?mvG0+5hm>C%*IYqrJI?UJAPydbPcfA`fRYoL^r!|zi5z^7 zbcd*5KW>+)&puP1nS~}2&3MiMX~S|f3oFfbyH?>Fv#gt|LgqKf0qggV-?%f+fO#dJ zY5x^wkFb-AoxI&C*qm74_(fHON?UhxlOv+q^cg~pH9K9l`|xPAkNP<5Vito=X9&X# zv5*%qEQlT}iPKlZ{!B7d@M+P(QqPTpXTSg48)r7{(~T&mOlS#JckqY z@p@^rlpLz(#(OGL1NGGd)sb@E@4}uDA(Mzdd1Cbsoo5#NK#O|-3nGWjVTrzQK zQ{(9!gU8nNbr%YnJ1{fczj?HKp)b9r9-gemH&ydPsW>N~495jE?Z%FYzkG7bUq7?s zhp(OcgV(P9@Wpe#{QSkAfA-{`y>jYzpFDPT%e3Dev0)GgwhSX75`DF3W?=FDIC2VnAS^pHnw7s-QTbrCeN&W6n=y8%<)Zq{y6c> zRN7(VNPumU>kyhb9I}6boG(wOy9=D%$=L+iE@Gpahj($DYQN2IPz8o zwZn4*$7ct&57iY+*s!ZE$-Qx)c5CO@w=Qh{!7C5E`@#c%eCymleCgs}zjpXfpFi-e zOIyBv38nQR^lzZ0AKSa^$eB1pHZg&H=rGl&wh*LwzoZwaKKC=8O{7^zG---P_npsb zIa)lM9ns8km@~n6ELR;!+18AaY3X8^9Q7$#s@Sp;E@7dp5Q5edPIu`1y4oG_WFzG zX4m}e`N#h3xo3axsb~M>`A2{H;>|Byd8)fQ;*?2h8onB4!^$&R55hSk|J?M?=zM0) z&p3jOg%5valQ5+diRB79MQOecJXh?#YKOn!@S|{C@2^*fYq`O4a+Im9nZDj1zIfsXx6ZtDY4^!ZTk@9DiDRp( z=Vv;PPE;wj`{|FsSMrC7AXA&Q(bSuZ@hbMmE=+rM}7+-v8y-8i`JjnnJjI=AIF zFD(4V$&KH+y5;P)^==jO^!yy=M)EjA6N4PFI}+Q(n%jIZJOpP|_@cdm_@F=DPrY@se#2Fy!%W`$861lxI>H(3xB*&&%0+Sr+br604qA#=Y8W+Mx57d%-H1~{LD zy()58R{}?Zg?+)yT2J6qvaltZoJ+-D+p_7W4?prxpL_Ygzy0jLy!DxX{>FO`9eFUI zCRJxl0+yJlPi87MT}LawVe*WFen=VRPCRo|pB=uc&EJjIBVVjGST7G%vjgSiKp{Pn zO>7#>939UEbZk5%-S68*27ms-fgine=^6yYH@p@g(ELIDF@I2GSC*R`(QSLc(g=_UCYiuzdMms zQUAhN`@pO_zAunDmMT3E&+UwauV!;!o0)oV)5f3d+WaTGXa4r=;lF?4na}M%mDVE# zPh4}ORVi(?&>xs*GTzyXzR(`0zY$Ay4mB#^d9aeI#zWmP)JjSR#>*3xswnv#ymEHK z^gq0D`1fueeD&1)t%DPXCn~zEV-t!h=>xS!HJidPFVv}BZha&ZTvLcoRgzo!$~z~j z53cXt*qP^efwQ^G(a7gduKDg$``>xuI2!x^%)&Q8lpH+(qy-x`S8yD4 z8cn}JU^cd2F%`E9SPbes4s38%CAUr*Z%89L9e)I#aepL8BTRi31aw^nMNCSO19d$y z;LrFKf6%3G)Z<${v9q!AX_nv&_FK;~kt;5^@@aluVeC(M&J$U+D zt@EKuPth0AFdWPfXQ=cte&gQsnfHL_E)G2#-da4>HPon%RI{VCOiwNe+fa*Vdb5%4 zY+4sFoLs-MXWd`Fe(*P*I`I67jgM~|-Z@hA$U0|t@tjK%HNpe$hPhI;!0JXG?}as8 z`MFwVbx&@-3u+%1d8ebp?UA(e3;kbz{Lq&kKK9;?13!I!_n*FW;Jc6S|N6xp-+plR zt)r9chx;%H9VLG9?BN?yo^ef<)uLb3;%;9Wy9^l5K|Fh#Z6=DUb*)C zI}bhe)0bcV<(psmU%&eGAD=w)W_RDq#bQbgDP-Dh%R(c+fxUsv6f`@(_}+NNdJug_ z7+A-9%C11Ix7-*lr-v(<$$ELNzia2r=!WUBR6OexLIST8W8w7!jp^Z@kcUHwQ}A|s80R@xzS%X)xUcvM*E2zqj`yAexxW+g(B&F~}y zm#?CEk9eY|64^n2?%_n@)pTq=QyT1<-m>xFwuz0mPG0`eGq2vUWhLw zOKTew=XM<3zk2hQ?y+!y8~%VS>hFs ztR{V0IT>_oQJYP*+to%Ug<(qXT;B4%hj+bub@SWj=bk<~|Kg$5Pwbl6JJ#^HaH=eh z5f4C<$+$TI`v?+n9q=2dsA38M&fUNq1LQY?iJ?$((9~zLB((Sq+H2S3nOf+(^Nc*^?I^-*M#Bn$4#QwSpel z9*%rAoxYmMYATMuVLMiuNRtCih>J$Oo7D$VBD{OPj^#H@eFo21dF5j1J|s7CiHYu9 zAe9XP=aIbm$O#%5J)!NxL>1ZRiSATYP|8K(j{VRXG5P9evV8et=kb_WWt znAWRybSNH4>C30LjdxwzIC|^Iy5|p!zi@c!)`78Sc1>*SEvRISGioSkeg@A-Ao)2y zLauqAf|>|Ura&@ZjzOOp&p{x~{D#3Z+kwS+X1z%!&v*74EuP7(`99NUwuUty?KZMJ zq%ezkld^7&4u@ohDb7oHrYfz5sTdoE6_efjX|_nvz3m6KPGXR1lndny+DdbM&no_5K8 za%j6npHbN9z@dRCb1w~J1P5|=0&Gdjp_Dka%IYbMXWq-ke4#O^#z|?MC{a#Cd(+`{ zJ>`77gbC*yIg%dPV+_H=>Oi49<0nVxY+j!^wa-q#cFPKyRiMvmlV?UXj0&b|*ko7^ zGzq|X^O%c{;fcP;Kt6tQuIGuZBaf^f=uagvHv@%!I*SjQjOP%iRA7WPa(8|S=fvSo zh-{}6@rD|K#1O+Ca(CWpnKlses4?g$S(aRUg4RlI8nu@;L zT{|1gsAyzb%Cj+`;Dhi?W|*_!++{_M#Qfe&z+H=l@~H;gJ?RTV(HU<~hsN~TX47pp z4Y7o0Ol&}k!>xs}mFYH~iAs~Cz8xk_aXRtch~E}Dtuq;(@6OD1XJ+czXfWsYWKlC> zJmWt~-$&#~EP#z?4;yfBoE+ZE*r)=SNyPiCJbS_fY0?WFD59idY$QY@bR6rV!rtuPznjN786hyR}Rna;?C<~XFFT`uyj zy6W@s8V~tuNpw@6tvr))opx6>5WZe0clqKuckpI9{Ij0a?+kQa?d*ECd;Eo&h4-#K z{=eP4`AUDa?)5&NPrsT;9E@fal0#@EH}K*%H&`u&8C^-1{oO0-vxR3@KH$&v)ruos z#nH}uDwYoiD&)`R!XGpDxv2J7E2#TgekWjmWHO!QahhHKMZ)xJ`F?a=i0 znRR>S*3A!(HFDK>AnA3-@P-melNDO3+$P561>>1a*J(Np>Z0j2@f&v8VN(=LN90h0 z)f7S7G1d3fzL`fBC)aji-(nqY&vq_=L*;N1B6S*=-~oMRPooF>O~@uJcgh>C5oJyg zaklbo`i)M0*#hRy6Vshg0^yh|h+A6oU<>Y2@Jwi0Bc8|bx){mV9v?0lCw zMRzC(&e^GYB7#d3Jpr^P!c3yIhIDlJutH}IMRZ(qK;ZO($8$E4#ipc)9)2hne`0#( z3kS~q?)95zhv#11bMhCjeC1!BfAXPfanPS04Wynb=cYp~o`Erf>N9J5rprL9N}KwO z<)IL_%UO)cEabbodGRNwK9t1s@DIk$VwSm$6*p>s`F z&p@NvRjNa)lQEp-9aof?toq@Wof2-`IKNT{!=PGqp2IUW~X*aZxd@%D#4N9cixG_6g_tT+i2qvwJ!*nw!x z6RrdkNO2IJ{jr`U{#nPg8Gqpe=rc{sHfI;y?>yh`pG}6X7ho9Z;^0v{(m?YwoAjlK zoa%NcVFx)v7)8S#**)Wn21FgVX~r`$sAhv4kj5FoHLw3jFynOx^8VyA_2SE0cD;S} zkz4yO?CYJrb@;-cf99+I<;K&G4~?u!)(d*%p+a`ZpOp-KW<1kJtOOa%wE3AKZQb8( z;aPASJhxi<>)1pjTSkhptf~ek8l8))M<=`Mow-U3 zMP$5B;bU>yAnru64-9L11YiSc)QQOMY`ldXP;Z>khJ*i_;UGM#cALxX)HP9q$ZLXY zyqw!Q*0XV>5f0!y3yrvRG}mFYFCVkv6i#ec!Hz;SBN6k4b0{!sAcO<%RbMWUK#IfQ zIl@ZbbUhfV>4C~8mS={s`FLl2HpSWO11C3DV?+|JC5H;vfe}0jL9K{tP11A+dZfv= zWq1#~F2LACT9E<~N$uox(dADn!Dp+v=Qi&6tt-zwv;D+kb>y|O?^?0gt)(O>B2vF$@C^U_A@GcJM>w47NkvBU(RH1Lt^Jjg)1demJaKF32#zzS7K+8knw%^5c&+Emc+2c`(@6haFWbPcvN{=74UvX zmIKG5s4g5#<%z&FG*ZdIVsfaM87RbK;h=+qA%Q<}kz9}%alrGFybAUeB40#$V{ont z@^#o(=n51AiSA$$T^v-OKjqml8z#y3qR&j6(H&~;JG1f(u#vEmaQH6oE{SAS=ybRQ zWIsq#hnMY7AqiDd!wqtRx16dC#hBE_?5E{Uticao9n&0Zuc99 zFZ}U=V-w*lucR`r;PrC3pvHN+>k7GIoPlD*Z9H4&i^6qS^qF^8?ag@w%x_?70nukP zt7a3Kp{j2Kp_2OV5i!Nk3l7${e zVuuu?37@bnIW?aiS252h6zhpcyW_FmWMVLr9xfCTfw;pCd**h#{1fH!WHmoOSlvF; zw|TOA<4AS1yWw`>Tnr$M5&C{~xnMjL?rY?nO^60tT=Ra+c1C>=M@|r)O?__9*D=3A z`svKE)_|_Xg+`eE1F&)htfXD$XYZQc-7~#g#_Q{b2U2k|H5z3X$g+sN59H8Kq|lM& zfTKp4hO9m$S5otrVVDC6vJwQ+R{!jYH1l<2wv3OQyh)PJo&@rBboLjvjg$W8W%G4r zeuK;aZ`D)oC!UuKlVKfn%yQ6cYY!4BcEd1(WSHmMc_vizt`32;fdx5zO!d|jx091; zBO)mZJ7J`;Xu=H?hS2Wj?e0V{alAUPAz$0nJ9H_X_}_aw|9*uReL{n>#o@((?+e=?#|OSi*DjcQN}y zjfOh24GEfT{Q67vxydu`kAlz1>o}gINAA>V?_f+QyMiG}LKo z!V}DGogUq`s&hkkX{4GQE@cv4@T^G~1P2T4kkL)5po-*FU8*;q2zACHIH4QkzNYK> zxq5L!Z*|K+b;np&Z>284JlNc_q|es!+XgF#r@9VJ)%T6pW*WtrN@=EEjA?$3r1fC4 z(XoqdRsj?Q?WBK$6j+gzhS{+4%wRT07Bq{4%|j^A{7hg*Cz7m1+3B%P6+3F#tbWg( zcy3Ab{iV-sDLacYvsUM&`fP^;(cM)L>Lq>yJQK@-n<>iO1a{N2UUA8jvwZ?XKx)2W}2 zB>#Ri`rjs#H?vU};W;db$Sn|DZKTYN8$J4kjIAhbJi}?w5bmze;2GuMQX)Q-jZamx zTe{18MjIRZs%|M14i~ph4R0IkT-RG(*I!=UQ%wiLZb6IrLqXje^#zNGL~kyKu?F>Q zwzm);N+&S786$RkbMet)VziJLFDK>)%ALiEfT@*s4TCsP+MX(BHue-Z_vSYBES>b|Du3c|rg}bKd#Kd7-raL$py%O{fyYM%AM5LVxU=)o{_Za< z%q(Pc3U(kO=S)-!H)60#71)HCTv%#?gmW7B;^p*N)JnYG4EPP~x5WhhfmC$5m|CnA zb`R8MYnWReNXE+RhkNH5sqsQ=s-79hCBljex1M|`TusEgbGd;+cDz~~uVhE^$(dSy z0@Kb_udW9$%42 zrr3R)^qJi`mLhE=I?Q4UbJ4f?XOm}0^ol&QbcdZR1HA&>)=ll8=pse|J`^7*qj{2DQsBlO_j5oI!lYa)yYyyRYJK$b*{gAO+7sZ zD^ktY5>fO9c?2aNiPRGDu1tC$ms(ZJO;l2og~WV=@a*@5+-~1sDZS8@U+6B(_ZDaS zD;Pe5?r8k(qTuRF#CP%&0G?Gbp3|;leHmz8_(>Q z!Xry=7%7hT!842ps|k`v+Dp^UGfD>N?DhDRNN2n}UFe$0)W%}D(P(};UYZCM2J}Ra zE8eLks_sO|l`Q*9l}Mu+EysLmjtVm2*#Ui~61{|HcKT2AkqI3+-W@y}`3_} z`b>mcO{ucK6pIXGljDW>H1>LD;2dK4WNEx!94SQmbLpN!7PCHeQT0h`Iv6fR!u4dL zH=7zMLur%a#ncQ2Ze+5_aMG=MJJad;?)+SLVQo)gs;5v)7m(ru&pfYoCF47W%R5KP z+lMN%U74A#+~QDmaRBzC2N=KaKToAIy|zL(_d?!YrM&v<0XI`#;R&2+RKO*{1H1ggoVJ~#Ui z&bw1Tw%F_liCHgk)G^ z!ZVD7VJ+Girl(om&NHcZr#YN&g)_U!;jl%(ENVqg!x7#kLC19-S#I4G%7%mWM5I3# z9xtaG@tDgME2YXKHKe9vo#_-t$i;N8TX1=i0`mrP!2l$>5{p#g;bJ6Mi-sG~Xgw54 z`lCoPXM&Obq`yBMSXIl6)${pyMnDRP+?&*LG=bIS=AQiK-u$X+VWz9Jd7!qrzp}Bf z+*2sQ$#YmKC}Ff7HF<`YCY^N{_z-CE%+k&V&k$z>%m(!vI5ZYJVH4;Sb?PzsZhpf| zZZvtmAMzWfKHtvs3hf+Z#up3N5B#RoKa;E-NM=cC+8|99<77RE%oR;v5Jv%dF{)b4 zS^%vG(0#J3og?7H5qn}#lfoW38gL~-S|aF<``j^)5=K*~;`C$S4655GpkR|e9jL-I z8ISbTs=M<{C-;&Jp%*ivIW@&8S<;{HDhTeps1*>rD<``1f}X>~JYMt{%Bg0(>RMo86UPW35X@SG2aYpFzcHZ@ep^<@%6`Sf5eJ(NzB zVi|0k!sA3GJyFd}H1Z?Wd^wdB$PiId{!aUYgX!o{I@F(zRFYAcoS{r?I2Y|HB%%>i z*yGrP3UFfUBk-2s#gaw=! z{3VjM2hlp-#%`E_dJ4jZBf~JHONnCi zB6ZH)WEn`D1{w23=ksG3*c{QXG-0NTL2To~aj{0SPLSJ%Z(xmY<(aIch~Ho%IPMRg zEk7l;A&_3X+vC^GGfAroG$n;cBgh;=)ceFhhcjrCP&dIBAT_s~ySOXQ7-vcrP&g9@ zr&?#7dQQ@dP7OQJOQI{sD;bBBu{)ETk`i?!>k^o=p(}b&M*YT{4+jU5sh|gwK{K^{ zZKPHl%;n&R%aNFiS5*$v#=W4u7>iYs@xDTKw3zSDB*%)`!9r$LDLYWe>+X2elU!BJ zOg4&R_0mAO(8v{?@EZ;VJVTH-^p-Ys=jJ=}-Pz2lVqvnB8!x9SsjSzVb-6Gz2Q^SK zy@Wjyn8|8avthG<7{pPqG^c^{CP??bvAe1XGY;0IlNiZZBvuwAl@wz#l7Jx-bn*s| z5-0Zg8Zev16qfP=4-{z&Dfh=Ec^lpiGd^SG*X8}kK9@kAjS zt|ek!sdyt6?oB0nVII=(4{^Uc=5;3qkbqtl>o+i*vx5==>#R(B7N**xNB_URY6<$q?YEsiNjXWefanOmPqS7boGOuTXai10mM#^!24B0s^CiRJK zx1geNPM3XfvDn2|h$oA&NGTdAL_+0wxGNch!3NuXsdUtzl9Wg#81FBnhHK?UHkl8{ zKr+>5sSxt?B?Em)e_97bKJOVMR185SW?MSe9oh(f5ZaTYkzF z^_k5SWn)E6p6R=o^m4Ewc#CI3b&F?Qn^dplpDCz>XM!|JB$mKuT5MaL^GZBhFgEiZ zFdIk+(2}vASCAn|3a}R7*@eb_ED4d~sEA6|rDt?K<#LDOUT?^y`4rtNyM3aT2_`&B zFp;Ro193DeBTy4We+3!{Ri{UlG>_s9dVC4LA1=Bai*}PlbZ#)4UR6#_ma>^>1~}DY z+2LxTzf$ZfWa`N*;~C>~8;LLmO~YXH=aXHT)IcWMlY-P|G;aXq;xfcB6d8GLV}J4cy_}BO9JsE7`!iw zs!NnGf&g!Xls{As$GQ{ov2t>%lFvkNE_|Hv+*>NN^Gy8nTJ&tx3nRsBe>yptiw@;7 znQ#I7Ve$S#>4e&_=8RS#O&g&J%m^|!TTg>$kj!{CoJMn6oyjvsA0XHf-X_mXpK&Dp z60@=I>< zsGwUq;q{h7k+`39*%boufocIfcNg>3M9x9hgKpFZ2QsO(jmk`|G@Q@&q+;XQaBn&l z4(0)~tm0r?m}g=$h}nSk!b*^mOvRbxHvlj+nS}u}OE{xD6w?=RW(vd^I}zYC$Vero z&wTSFAmTT`^AfYMglCfFAWOpg^$#X7F8O0L4dRy~ZA+AAjOZsrz>GlAusJjd!>=r0 zla5Cc7MO9(cxJUi`q-LjV7P0Nl`?_H1zFUSJsQoxhivvm8@F`62fiU$1{z;UE}H!t zr0NZ@d19xDT%#ib*=9~oK(R4R8eWt({Dd+AKUQ=7sTfjcL-_=mx3497YW=q-LEsgh`!86HT5@p698Z<@Q$P^~giDG+%%-$yp zK$K3J%RsCFX#s`6?8LTNcbs=cI3+|Q;E?^C?B(dmum;T7E=L+f&45f%r9#D_c_ih1 z%`DWj zz+H!J^b{dGIp{DH_4~Rr(XLbsNs0bKqLED_bvD#F(wR&qG*8&&)5u~F19CODtm~>5 zQv-r}z^iJSAni(>-U&R%|&d zM^>UJS=);UNwkx-YzQkmfn;nBi`~U85Fnp(0ReIcxsxCXkdOJ2PYdit?C*VF@=sQE zPtVAbjbzk~zbH<1bsflu51;q!HQKa`q0?8;jtAkiQ;$2fZYZ{7Na>1PWjkS`)??=D zJRXqzKkehk9+KKL8cf^W8F~ZpYi)6Z*?VT+4kLP>)qv<4$pySBzgsoP$ z(dv@mK_8MJ@#<--*24$bsfOyTqmrf9tVcUH=rNWT=%8Z>nL{L8?z-feS8m+|a03G&^E-PF?;oEX9?m8w-+uJ%M<>U3m;1mN za*jIvX*8M*$A`1M)ogLPSez}F=ga-`{rTCF^6=@M*?2x2q(LzBdr2QW51Wm!Q}%=8gOHp>ip)^0Oo>A;knpR?NhjGy&BE2GUU4e52ov-@7`ps8HtY%ZRiiq4|p zg_g#fcb(o)30-JrQkC3NX)Ptpx{Bv0L5We%qGgOx~GY5p#$D-Z6d?p<5`rBhvUh7cDNj`mW%UmKmPU069~E8JtV!q z#p*7o!%|wN*DhctQ(BtF3z!>yLgcL7x`t8mT4sV`j-S7tc;3;0ZtM170qJ!u{Z->x zDVi=@EK;6ym1_hFEv-Ps5@ac2X)Z)2wnsJ&vxGnku9Y&Fd5*Y5G>wf$EgUXZP5RM8&HL6gFBVR-518SqT-d~xs1$LG(| zZrp9qT7>%Epw|xlMkn-w$uOOz=|1^&$%q`$hX+d{BNvPDlf(J5)dH9D(}U3)tHmfj z41;7fojo`_?6mu|6m9ocen@X#>w{E8OAXjLl0`%bIooZnjAwsDwo;`%sAg2P!Cdh9Q{!HoMg z%WLBqi9T#;i}bM5-z#Q&pB5E zX3OGMpC@7?$1^TF>G{Bb6)y$S%&f1sC(P0nFiXHF%@>{=hi5A8MQq3tpEG8l^rAOB z=U~q8tZ8+xl|AU38?sX}b;T!nqux-`F6w8Q`Ia>#lupQ5j}A%u&y72F=r;&G+RAi7 z>9_VwT5U+?nX0>*Ezc)f0W1%K-pU``>Ga9}+-rpk-#_Sf55nMxMV|q`e-uQ= zVSEUT4bp5o0dC%z*O`I`oC&(9HkIIbt(De2f^nhOX0qq<%_rZxx4H~kVWY}4dHizy zpaDPou=FGzkE7w7l+i(d6-Rf|;XS&?Ove|q39-Mk@$lX>ez2JA&+d86$#OV3PDWvG z(kDXQTOl@BGEpKAEx8??){)C*=l_&myMk@0>!}9fYy{7q;u%P@_}C0*Y|(j@5R5Er zfocQf2RZ~csN$y6E)%LT%4Q&nkx5U5!#O+YiUXZO`1<%az9^o{_8|M%<8E02%Lblv zYzw3X&sV_ABUTMcS&9TfG=Gv)53}(nqCjdxqSY27MjP`WW6pLNMp@DR_M%8f?clJV z+!+jyz;N~oQuHCEA5xvCbxgK3#bWsqaCn*=f8*)Oy z!1Hu4Jc!cOFg}W-^K?izq(_U{vxDVhd>y0s-ed@#j~92l&2$kD38QG3gJ;68j2x;<*IaR=x1^TP0a!6i$IEQVi~zL(ck2u>?Bx9h zHyqBQF<>fdTfw$C<2kRr4ro>vG+(6nc2;BfGJekQV(xbKig+%0jITi2n$#Jd;T%mc zqg`RhEC#x`Q0;;a=>~HOvUZs;B_ko^c3?}Q!U!2QGJgD5N)X~;2cC<=^a6AovR~L7u+r-{I|YxJeO|7Wqy`h z^lS99iRav9cdb3hgB$!@Zh(9vKi`CBXjwe5ux^8V1~M7w>&O`tVADc&m-Zc~j(`}k zX6)?vC``Au_-7^R1gj{$7pG_KE~=GROSUQ_x7P4nB!~37z2)KYvnP+=CmVF$8;l3E zR_M|zHLQoIXcTqYOM8BQHc0l9bUBRgjmP&VlSfOcVh_p0I2{e|j+680XfZzC-@i;o zd%fs>81yVLsZt!Ya@gl zw#&zyYy`K;k2~SPX+qqJ$zNf*6I~n!_&01852qCj@GD|!2nm8I@(Sh+D7G}?>igkp zI64`QP8;3?c+>h`TF|&9w5*HDal?tCx*aUi>3N*o^}Mv>#VwjVOXFV#2>P9RuiqJr z2II(&2(Jt~!6@i0<9HcUP8jcxl1ZFK!JzMxO`437!^z}s$DdM720z!SDX3{PXWnZE ziDk(u;%1SKVd7@b@eH*VU!+|nyjbgX{85FDG;4RU5{3&tH-iO+H#`e1D+`r|qDm5u zDChi~zE)=73+^gKD(TI5w!7Fb6VCuUBA8-eW-Iq!#WOY?E{+@U+zpS1qdQTuvRgcq zxCKSK^#VNm!F)8m>l1WqrH#fANyB!RfX;5vYV<=t8un7~oDlo&4r0R3K{yM0`%!#2 zo{p0P>ef5W*sI5FZUGDt(QJ~YQik-kc$V^Hl!lVCX^afLTU+#|vqflI)^&J(tzemmFLm9B%i+#5XHvz5z)N5pHh1=CwplSoh+99{;FCb&m^r@7_}CY z?;poU!{Lf@aKsWAR;=uc6Fvh<;@}Yd3>0&d(%3W-HSh4$tBQmQMBJMnf%&-cWv)wjMJ3kLM#P z0fzXcm7ig3W3%EmjeDdz2uMaAokj`M#I964YhM}xd5&ipkkRi1vv9C4 z*NZo-)`Cj4i^&O|tK?wN+L{<*rQNDZ(F*2a+U-yJgBc#YbixG8N+qdO(rT5=>NJWD zSz)-BPVTn-DW92_MfP*an7>7C9B7Yi^io%6vJeoYYc4rRA~~#srDTfM`)yL@uGJgD z#<^o8Qyro-RAV@1-eop>nT@x$DB@n%8?Q5%GgN1uo2w>p_6QE2yhleS(l~%D(bBmw z;;a&OFx8#kgBxPD@a##8dmY>7ynHZ~nC-x_My*g%#b1ZRR+=q?cA1}L(H3GWGC@^l zT#6t!drz9X{Nc;{8{Y;$sRHh3AHWnQX5+611U9WX;pYz@`<6W|ue%5vbNpj3{fG*b{4M-Unv?F6yGCZ5fz+nmfgxR=!cjfq&cSMh8zmA6K3 zFou{5B!~1Go@p6MMyS{5fwwT6b6Fw6c|krcpGxC9{RTaL#S)AGGv%(tQ*bbf*r-Z{ zAk?kT?6z8Q)Ssiz9iE|R@QmR==JRkcV^QZw>%U(Hp8tJz+t@(s%m4XOJOk!m49~=0 zN`l0Zwo@arBW*UdlNfh@RlEV&_{fY(9p;Sc&A8zWWpo-|2=)b~f*cklfre+I-h<>$ zKR$#K>3PL!wGvxAfzSrHVqq;he&*WYm9^zQ+D2gPwc-ZR9LeqrD-wbfewN|gRhor% zapkq@y+I$dG2sa~F3?4&Bl@m`MjqjfC=;XM?E&?ItEY(PdXre;9;1zMO8dm_nF~|t zd99@5rR10H!qvvlTV$EyDwKOlubTu6gCqI#8oi;+{3Y~;8U8Ov!@vJ$l<}OoJ9sD; z&(0Ce&brMPlka8ntWibNGf0>ViGV!YbsYR#HgaT{j zUWvO2?vqx}PLD3tC1byxP%XmnL721EMBXr!Kt`YNd{rhE_mNlN zLo#-=rwuMaKXVPO-Y+Mg%XAH_t8PC{06^j&5xKzS3 zg%~xN@D55%4+|_cTERczK*UBk*aJ2Im@R~iDmMQZsLsJG7M%E>ZG>fR{b4i0%&b;p z5cs2bus4kMlb9}Ft2kyZ&_R;oTR!ObW}Y_?pB_HOY=Bp2%nauHgXu8Y>ka07&di-C z>4j7Vq|p%PhA=tzg>Gj=JTWHC6>Nic#>mzJLX*u#kMTo5+EC45c_lpOZjD=hE~}&) z@r?Jfxb`!@&`a?wkZ$hCjneRJF1rHTH{sdLc^zbl{mAf2Io(Y>38D=o!(W0Fl2)XZ zCK9 zqvPfBK5H>Qo6SxqlM`GVuk9C<~>Z=4)Iy0dyT86Dv~X*a{56IH1D zb3IRFr${u)l=G|M`D>+_%luqc(dGRN)z{)#5?$70hS`P`_<(0yje5K5_p5?xarbFB z45EH9p0!j~awaPxPzB6%+)_NF1X_)_NvWy$>&S>8N0KMz}BDc=G-qeE8Xq|L{-$^Y@=W|Nc*Z z_}f2u|9c<(#;^b0+i(5Hr;omOe){&w>aBz2gK>JC4!MHn^l0)sNk15240hXGwwQ+m zs#sa_=jNe)1w4O!yct)KT*k2N@05Pl_*s~lpsHkTZ60Lxbr_z(Fhe$5O+O4G^YyVc zBxg!PHM1eg9IfCJB;$9LH1#^8laZ7#v#eG#^jh?}g`#P2A%Q$2bGCF#riKnY`+Zsu zEeMon+Et?JUD3~OSuPN)zSA|IHZlXaYKS@Uy*?dB8+Ac=g`^R=S;!zorom=XmhiO2 z^0tN5fibi%W~Q`i@Aqoa(i`8SSf-s|^o9Q6!;5#n_2!39F2D2W-ggi8pNvPR!|0$# z&JtxfjZv*e?g#D>Tq~JQW~W7~+d7YAby6HjhiBW_Jm4i%Z|IF2%s4l`zCXssFUNBR zW`JGFdr_{o!wz)8bG?Sy-q_jBW9210W4t@<3Y@^O!5EQ%6QeFZ=LnCMff>CK&}4IU zMyaW&7YRG&IXsXsX*~5Ft+8YghL(iP{I`;sSy~Ryl~CPxl(#U=wol}RU`kVCe>gXM zst&yf>x_4iOD|785%=15M*`N0YAzFap6fz#P1{M_n|E8oIfh=e*QOS-IRw>}>bQn~ zhKe&@YRAKmVXh2)Wigg9F}7XyGG9%S3o~D3c)07x6{$&&LH0J4fdjVKcEAch?&0nrL(`-b)x9q5?XfbPyL1tZbyR=Op zsy@&a!`R@~_s70J>U0>}O(b0&<&pEqFaAYDG5B|I0RTJQ|p znB)*hgXav=>v;C74QcGNg>Pz`__8FM-cqTg^pWPy2# zyJ-jQ2h)DEjMJkeA<2IkMGWWM8}w(=WHg-i0=j|>+ntyY440~goJvj%cdTqj0ld8< zYEAkm%F^4P{vp0$K^fa@f%Z^(?5sGFqGY=3cl zu%!9!-Mz)xd~rUXpAmLR)5AF4>-XnOXY;#|ykM9lI=kaYut~DV3w4oQ_#7x(It!8~ z&|#iiP=v5p zlsrcMi8n?nwhX=7Qcl%kYuQRLGgky@OXjpeN&#tX!2B8)wd{~A`#U0=k=D+BDN}R_ z$(BKP^&H+lQXGL7;duke_D_zpV-NNVPIh909TR@pc7vZyQE+krb0J8OA0Sz`(qK^A zi)kjq6+F{ilyTUYU^zb*Vnb9%4r8|?3Pd!9xRhDYFZ&8zso)F487dk)L(#_1it|CY zJ3)Kk)1zA*VV$Ty+n*k#18NEBtKe-{B-vFjy^M!<$;7C(L9f>y(4rj4L83m~-tLfz zN7|kU58#?%xHMG_FvHBXI)zXFyH!_3+TSWUJ2dTakcRVTWczH zJ)W<_wmCrHDA#h$iR3Fgh3|T;o(|`*HWVVEl-^3JlgripSL$cMcIL#(ynpzX;m;i= zZc6|~Pz{DbIPq?lku7`+yOR7YX{FVm!w~tZ57|z~sEY}~#4Q)%5lGVxk=Nuh;W=PG+Yh5b3DJosk?p3 z3y#1|+Cu{_=9hjUKVQMK+*0j)m8eN2r3HNPga{kka=gdRI-V(~l?GWX{Mee&bOp~E zMs(zC$#tOG945$hM7!Mxa7Y((fx(+CKtLJ;K9at?6H8flCy+6O+4GT6G&^OmgFC*C1|RQ zyA@)CLnOb=@eHbgG>cPk%g?Wj*_)oYj%PDNwA;hB%&LGlSU2%=NkSV7m0+CRZ8^nm zmGI1ig*3f}pGo!Z#4;39vGglZq+u-q_zFl-kluI-Q5;NHvk*G zAszk|u7YRxE-IlRd^HJSds%1|i**{FYfK`paG6NegJm89W)fYTi9w!iy+NQH@4fo& ztW~Do1b27DcY2HGn_zn7cP1^aJY3{R3s2`iI@54xhc+her_A9lc?rO)GThiIqzep# z9KF9AdO7JCJ#y-Ec$a!|Vn5=4AnA_84qORo| zpSbbGnNR)<)73#Qhg&jgG^YlSXmRlKlW_b0n~uOs@m&66hvH)A1$fRQToUJUsJ;=; z1t%MxaY2LXjGuJ|3gWp!lMQW&OmQovB32SeV>g~Axg0dIDAy!ry)2|di{tz<_Eg&# zdaoi}Y*P1EFWs>V(A?(4_{8&;g|-FBw$Kl9YbzbG^1i4G!Lu-lrqal!eDH7gzswOR zVpKLy8Tx90R|!#30HmPx+vw6{#SE7aQ7{Q)*_n z39&J9os^ztw>(D@GB>>;Q~a7VQnuEz#nw83J8i%vuwCdGk+rt;twng`|17RD`4i)6 zmn)dtuwPDXSY*^wCUvXu`QpD+x@Tn2)ILCe&zBRv3*XKP|e!P zu&qXrD3E-)bW??H(H~C(<>K_?51kTd?a=ZCw}WOb5wpYpAQJ$^+7hj@tC4g=@5UBx zx0OF$bUQSlnwt(u?3TTzv9aOV_T9aMh|l_R-$gSFbC0FQ{iSWbtkSiAb^q4xE92@{ zvu}_tzt`3CVvlU#*_rb%eq6{cN3TQ~GPj_{?Q+O^64i( z`}p~1=b!)lvyY$u^uhU$KYRYukMHwy@#Nlr`}niZKl$UIz4P{P>%;4R9<<~W{lnk< zXL_gem<4b>{^B+C``SW|9fBe}e&p-X-FP{ILPxsL$KYHiw$1nPT*MDsH z=>11e9zT8b^y#A~51u}H_U!THlc$&VU-|Ia`D%Q4?j z{`=s)ZMDVnBmY;e-~YdV%j5FjZ}8vx&zC(9@}6b2;c|L% zOJ=Q{<=D}#Lr1&ziXenM>eqJRxRg^{Z;PQoxi^Qm9uj>f7Dg>ubf|5JC_S~&z`+> z(W1GtSGg=*vQj*H#hke-=FS=HGJBPHxv=%P<)T%~#p9OCw;%JXK)6dh{n>u}RmuO1 z`RPBf5pu2m<9}dI_^-5-{H+WfXz`POVom=sE^=A5YSCQsH|f^rfi53^gXDjH{x>-k zzy44BU)8q5(1C3H9m?@_h@Nm0L05sI+FOHcC#V6(hD<8;)9AjyfY7o|;5ljrKBX$JLOCr)f(| zpxsfZ(@CJyL7;8J)3m{-K--p*4PVWICDxM@>aaw*T#+8c6YF#2_1R)QmQV-Z%L%n; zu|(Qjkq#}sSeGZ%5(~7tcJ6lUK+qr8!@rhC)|c+9EsLnFiiGN__J1dets^4O_+&)? z9?55AbS=dyj!AEhCmN`pUM4f=2;kkz3(mu(0W_! zPwRD&@5_tcLA6ZYU>hSu?Lu)Hi z*Homgy`HkBI&sJ1i%W~m;&WL%wj5i)7c81Q=tS_$+`wsh zLDNtAJB;aTE9NNLC~&8l$hXqd6?6G44o8m1;jq}W6nMPJqwM0gj81T!kmNclb<>!L z&Ewq`3^UTz`QOa5EZaZw%u%d=e+^;)APQM zvV9BVww9#se44xWVUFMZT%SkT-p|f@JUQp}m{7gzVdhQGFeXZzL_xk6Jo@KzE^#$7OSV#xqxr zqoSy~b>a9^;q&r>9Kmy%@3cN$+pF{Cd+P|ht176A1cYYr%$4wrznY$!%JMlQ4sIQN zXxsQh+kQ*kGB#$@gk1}Vo9a=v{J+(o!LY2F`Sai9nf7G9R(m`Mbvj6-*^Z}T$x<){ z!?Zs)@=WS_}eE+he9v7oF z+|3Gnkr(ik$oECI&x@=*PqVzAoCDP!pqd67Y(F@?tiO#HbqY#?<=%oz`V#h(Sp8`{Vlwv;nVV1{E0VbmIJIm*`HnIqJNn(@pQ z>9EB_95H^Cn6pG8O|Dp(Cl<&HG)52YT9h93M`gtK%9y&F#F^`)Jl9pn;m7azri#)2 z+N!8VwHP*lbVc~Lil%wvx+HHfFcYILmEpNWk~)w*05$-AU*s=Qq2D_oebEQmp&V6o_o!KT6n{uBkFz;V>TX!r3awvRnVcpjOu zWz>O<3EMQ!2*%CC zMSj-q_@nqbooESk?S#6WM6hf1b{u&<%6qlhLXs}zgb+#2Y#}m+E=NQp>(4A9{M>-A zpdu70>uBk3Ts^<$a`>mJZuO&o2aDKfJ9d zY3sB6fT!pEo}J(G6jbN>zM%9h2Nvz|By0EMbGx8NXLmvm&$!>ubiJ493YUgO!>AEF zz%zyPHt-CWmRj_>%EN0b5C2}3yeit&#lldR4IWu6sXuc`ZlK77GxJy+5r;c=c;BO; z3r(?jo7*yadkK1 zWmS749$A_ZbyTDejE#px=Cnw%H$^)RjNdB>)%b*%AMp)!RD^pI(Wgax{!vD92=Jy) zizHWH4q~G9yUVcay>E*`A7up;#jm@Q>G$kHz>|F6r{}$%o)37L=R@mxE-bnQo*$mw z@$k&{`=__j!Gq4y6wmPIEw_$uzIklpjiVcIHmo|lrs~M*isTiWW{*}@lxMSea>xpj z^PnuxZ2W?fP`Jox)S2jI=b{&144Va{Jr<1BRFvn!z2(RelK45zGn>m|^LSi-_jVS0 z7Y$BypK{b~;;|hQl6Oo@+&(d7^JLe>BP`8Zwahb$8$Z@JL`HHVBgUNZASX6$)DQKI ze~)KbPnLcDQ-A(DJWI{Fk!RhGV(kthHA}7{{@)GCI}&Fmhe2Y_`g90E4rvS<;F)j0 z;;XYnMm&+WNZwLSx%Etki6s{j>TV>|-)vOf%>*LYHIRl&Lj>$t>a-XG_#1A-O2alC zxh0?Y4RjPI$%M)zH1K%-UKvI5c17g(3KB~i*}hKLX38K0>?`{ZJJ6 z_Ts*ZRM*NQ+g=m|KQHiqc46LY6^kF3exw|HV78%430#pWaV{>U?5j?H7SwN;dN zZ*a=mzwBIuOF`(YydZ}S_WhKRxk*LiN1nN=Dhe+4{ZqG3Ik6Y1rUU zKXNru&}g1Fn6M$kGc3B3yjEL*8d9{0oKP1elV~B-0>IKkB3;ds)ay8iA_6TIUlV4I z-y@LM77C3_jV%Jaw|yy3s=t|1cQdK(=7IW~cuu60L?bO@+OTorMJ*megNePZLy6YEgKyK(sU(nD*aHad5;HdhcUve^QZ<`^LW^W=y`a9%bGQ8{+! z?3{@Cd7(}P`(~dHp0&rhM<;6}4rQuHNBc93oQKT9<#Ky;G7H``=D6qRqr0XZa+`F> zZNkAFlagI0rfiw$ziMooHmxN!=N3pdMm(04q|Pks$#|C7vIYG>V~kJyNI%Qr8B(;Q ztIaGWYZ_pdsx_s?YBOD(lVw@%V?EwuLL z;V-umzur7d7`_=(e=DYePz}5pH5z#RO@tGgZRQgg6W?Y;@k~l3q*_u<*R)AlTT;Q6 z#u6Acc&?>f`fFJzc!oZehP}VG_uZAC4_5hZbJ!vl8^=IYo`r0d5CNFW=5g3O_%jL?gSxjp?&pvfHYYE1*2S>d7ei;C z-aEt3ef*%_T|{i2G;)A_5zdc#>Ka>T{}S&x^~A2psh(4h?3#Rd=cI#f6Oy-&OWrol zfAy%=)+YZT&n$U!wgTy!FjNz;CHk-M%+nwp6DiCjFf)>MW?6=rXMqmEnC4li*IA_7 zQKZvRpkc#Rut3aUb5+?q6(CKY0Xd{nhi5RX4wB_~YH~dMsEJ>tLWnMx%GgS3=3AFJ zJ}o)+q2}n9TSvd$JW+o$x#3oFgM{Q1ST`jGY&?)C(oB?TgJ)QGqa-{_dNfUVuB{?5 z`wOw?a3D>I`QWl$5!7yvN|hq#motljSVe$T$*P9DZ?{M zz-0+=9^?wR3xDfT5Hjadgww^anU})mUJRX+AM6ynchaCu#lfyLGbRc1lCd!G>E0r6jk&GeP=hJR|(r0LhTdJlEfdm+@*6uxZs*N8!Nur9AR; zMI@;HLh<~mY~ROgp$yN@E`(f8@~Al-@VY4ERbj*{if7873C}V}do{D@$62J%@k9pc z2bnwI(nuW;;W-@^y|pHN19-l9?Dspz)|?1mHl%NV4Rt*(M+~t!0I~(1<&{J`=8Y;2 zcP@%_DvX#_7(VM_s3Rgrg!j14ZOz0iF;9+888aJ3}* zbAN_2(;{I*zcc(ymz9gRFQspIr^1dsbCcTg4$o;Te(vEkOy^|uaf2w3CP%G5%@S3=m}a^%?@ zAtDEaERDQD3x2Dorxv<#(&ec6#Zj}1B4!nbI~In`CfwoXi#Fr!48({;I z7s)T5-uH;-1d3;e;~vup&%5lCcTS3P8z1jB4*qOwY4lT`n}%mPNRztUPx7;D#$aG( zc$Pi%{VYGrCTD3igXw5DcCnf62{WF72TW+tVlZZM1s)iB@xasVM0+wJ8TDt7Oi7^I z1rkAeUHF=9S@Jq^JQ%XFoIsVr6~$*ADru-vMy*EWXG9K?I`A84w(-dq@(r~0{I;z6 zR2uX7#)*bo(G4~G8<09ANrQ!Y%y?`=?e5<34Y!VOD2Z7$XXp?OC3QAOfyI_* zvr*zeeg>Ab=s^zBX6e?-G{xJoILf&=YEE&)%;NAFMPUvXLmW0P8KSAIKph+TNZKgV z$+37^8fqTPM;t-e@TC0NW7@IZ(~j<%n&LhwamTn=_i@4N$M&1Qgz<8kU77_DHwKosc-b{k1 zI*FtJD4VF!srg1B{jFmExAOg8uSb2p9`UIx{6ksTyOPMtvNTClrLuST?AzMZt_L-FC0iLHG+ieel=YwvOlH4Z5xQ&n4GI463PA&4xBGYs& z6gU2&KR4r-j&3?y&V3& zIP61FgoNj!5SnLFzANxY@WA{MjdT;La|zN+1&=-(%9cAYg9o1PoLFC#wkBcg^d4qb z3Va%7e3JSG%_L>iG}v6BK(J)euyeFr7OoWbm;5-P6woly&i=L9WV``l1_^s22{36(gcPx)=y5B#{#HsOx;Q!BVnleZm;4^`Akod_ zx*KRg9<04_@OyR2_sWE?<#B&p+yCxz__GWCk8=I*o%5+VwdY3q?#kmkD~`FBAKh7g zVtdH}zwFQ*Px2yOU*7+&B=nEV;U9}5!SlP~eNu}?DUVd75j+Ub5~LZU-h(Vn#c8H* zxU;d`L6z?a&nGwEN?Tu+w%TXOWK$hIAqNbLStL9IX%e2Lg4uG>FjQ8M_gpxsFnV!O z^t_U&`In=dOCsl8jGTWw(6LYZ);zSfSv!bWkA%NyUf6X-qZHRYry!!vQ|Lp!IV zx02)rq$h=}8Y!7}mUK^yURw9F)DOgR529PuF8{7iB(l`8-+ zoi`AeMfwn6?j|OmU4;hSNpFR( z$>FOD`I-WOGLMg`UtYhVU5ZXde6Bk2{pQhcsCW<^tglIKs6o*qr5?oAfajF@8uEQz z&EfjnN9%4MuCF;#Uvr51%_(&?sW?}DyOHvxGU;P^{M#$BFN^81_)ez( z?Nh$DGJI~I@~O%6xu50tFn8~h{NPuGVQ()-y(@`+e^?K9ZkcBr$`|hJl{;;P<3eamPvzD6qKplE07~6LCIkdJkvAJ2+-i!L|-?- zeL+dg(vtnoCD98@q8D6_a=8$_Fv-KAy|DqGv|tc9P~SlA;46wmYbN$e^L9-4nVPX@ z;z`fRCrEt*`Pu%E`?Q1Z_Q`Hj5A2wd;5xY_o=ph1&3OLPxqX>B^G|rDNTzw_$jlwJ zlrfsX+?40W@-o2wQ=U81Y)g42XFWy~$s|`ucqTBDeh7&A6`xWT9fg;=5XyTLMh?-P70+1^>&c%h4t=S>Cv@Oj<$*8diJ!}oK9?Q%R384mH1yf4AOL#CUH97n;=c|obLgopXM~@`NlRTUJdiM?aypVXiE8p_JPvj?2=o^jfHYKGV3lb%!3_MpBo4fVQ1?o;8< zDQ@=3JEkV>nEHP?&r)-i__G9KgKlDj?vT80SH4m!a({zEyZVVpyMvm&O zz_%g5%t9lKBj#~+I<#+hBqs1BX4G z=c6B;k9wH5|9)QVy}YWfQ9-dsNZu{8aU@>8EHGQL)x{$72i_C`kS z&EvJVPSo8xQGeqIR9khZwkq{&)sZiiDHPAifSKm`kFogqr#y4`T=v+ZeRHChfahy*i>}4ZFNt*q&*!5TZJj+tLnNYj zMo>X#oQttKQv?0|E5@AmnUU#Zf68l0#-6F*`Gn{6BRi-4n>_z~j_xnz4OxFyY27Su z&@L^l(KYdBuDYaBNAiYD*!a)+mOHl)2m${M8L z43c?5bhpXb@W&uczDGDA#v&B(R73(TMX~zK$s@~;hTqRm0Iv6QqVMO#-p!4Dke~3l zAn9e{;g`k7-&{%mP>g(5v&rrNJ{nI+sG48NfTc^XXYP8J;&? zOWnSF(jW!#&v|B(YgY0C{<2vkFC{F$7QX^KUyXIX5;N~|%)H!)1q()XQpTVL<U9{OW_4*}eQ@)fbYJj1^|bf2Q(n{4y=I*7oN;UyO3>3%ciE@7O-tTk|1*E4iW`#r z+?br{%Ck&~0<{u?|??@!6_+>xUx5myUS`jUww z*@83m+?lV_naLP3514tD)SQtwn(-_N8C$sL(=~}4f6jXofBy73i z<}r%oqYXC>L-kdM>MB#eSEY~>VijN}VMD_6^*H$R$Ln#R`rWmdCxrpI``6w-x%2&% zsCQR@bnyEUOy3cn3DP7{2fZaTrF-8L20*Vb`Mx4o0K8sY@RBV`lky$0Xwo!fct+%? zIk~YQcKx`)whBVDQ4pI^*`U>!I=E~;UyhHlI*+weiV~MzjVJzmB?de@7st#y6*zNj zS7X$ysmW)+44g5*#QwE^x3pbL)BPMz`%F3QJw3zAK8@zt!{M;U^wgcxQ{1K}@0fOA zyM2p!OSt!=wBB5A|2oF@#kYo>XPZrYR zi?nz+HnNquJSCw>O(5NHQYbba35cug6i&P*51$je(&`6yQgaJKqqVOq}Sh0tGjjl2cA>wt5RzT z%*haK&Qhe~KVFZe6!W1p;obG9TW9_AqSrmU81eRM^t+OXcO^mZFi=YIOe0Oj4=K-u z=qLK%9^#7v3D1(&Au7^nvHK|s&s(X;xaE~BOzQ1<{oY&qz_x;}4Z+Fks)|~l%`}DWl$joWA zH`8fz#%DwIA&^{Gd9c1Zh2|M2LBewd@n_niKb6NpAFoG!DvSM47XGqie^IhKuED;6 zMPCEbA@8pQBT>IE2_c`vr2}cCiAz)WYJv2Ni(X8hh1BkHJR$H5foE8>q{DK0%W>bu z-R;^a3jUmDe(#R9C&Qf!4=gE8T2hMq9J}O7?2^31MSiXmO?A}i3$O^!G|#FE@~+Mk zPWmp$@SjfcY@e|Q=Rx}up3{zbO#h$a89kKdd4o+Qjb?d+@@H6dli18;X{uO9ZV1X0 z>pF5Zr6PI5jz`pyG_qx8^$|9Hnl~D2&OhW0if4I>X9dIF@4V0NiFHTHvAnL9SE?8}u)ot-pU3JlEYjS9|yDcbey#Qxwl9YHy}7 zJl9Kku7fjI6LY338#K&c$`cTwKV2t0e=3jqqYOqJfh_&x!v1p+Yi^(ML*3(J>3+;C zy}uHQL{0OID=h?RO#YMLK`tTESH&5gDT^jN(-!?a3lZ8KP4IiCw%<6m#dDd1rJ0ce zhwv;lXS$yvi5$oq_*I7yy$a$MT}oM6bYSVV_{CRamlnk@$%$X``=Vb}#qvB1l#k_{$8)8oz3l^T*EXS7ien^};|Rt+{)ZDy;rqlBA)vNv00=QNmS*}GJ> zd@V`MnXhdJm}xa3S+66Xh#qWip-d-fnotF2x}eecN%1V!?+K*k4SEsjchffR(Wc$t z?j48swj0{dZgBrDgZsDdJF(x`;q3>s)@iMxpeK~}Q-nec_M=587I0Kr8MlcI-SFv7 z&bNmJwKX6!yY^mA-Tj<~`v5rmPn89j3GI|o*Wb-VI6-*+PW%}IsK=!|AFit=l?@^i zHjA9Gt4r6=BbI5cwD%7}U#ln-ExJxUuI5(#= zz7A)6=K$#pAA}9Z6MGzvgJ(~NW9Sm@nv&u^mDKB8o7U@^^33dtp?L<(E$}Se7}J#J z#uYIX&rOE**{bvwf**OdOb_L6@GLE8G!~f~8I}Q? zkZjOP(WsA-abH@hMm_Y*dJY^gdD@5>(|?^dY2f%V{l|>#GI;L52^+`Gb{aUkmu(+a zMcm2KX5(xq)Z__N1Z;t-NPGFrDfg}(s>3<%W+uuM#BcBaImX!y4@r=wvNUY`4AFgr zkkj>u&^0HeJWCFP^*37Lxhk5z%A;pcqX&*`L(;|b5%Cp>2! z_nZNN=i|HVQG!0OeRAUeNuDLUHU6bP|BPp$4w@zs{fR#_B-0NqV$6IAo)I%Zva(4( zNX59Xib+omcm1-;p!=j&z^y;yQiq%n_6O*$oh2JBPd; zj)ZKHs*tBPs7v2V$3i|m$f~=IiUbaQ1@%%^|HPSF;F*G1mS^TLDB-!fsXsU687}?# zdR#Nngrmur6TR_HRxnZra`ne+VSxGH=Q-02+miyeOlog#qm1LQ92p8_7?yp&NOLSbjZjaaqig!i2>KedctwHW$f}{RTA8$j>64{F2dq)BR_i32->$ zPk7GonMv_Hi-H;cJpI_tX({g04(yn@Z{6R>8!h`YHSGVCW;e`P$*7MC1+y|> z2H3_uR17<}Yd?6>FAn4Sj-5Vmg44)pzjhnsG-&kZi8G^DtY16PY3kr{8fs?P5+*ON zEl|)f(=!g#v5UesPqEO}1kd;bAMj^9D9fw3 z&KY$!aMroNnP&o=PW#O~gcIz)J4z8uDx}S$$iJp|8?4e zu`_?|G0<_q$grjBl2&i@pSx_y7>CxDU3nsXMR{!{CA~S5hudx@w1_8i{;ltY_{HT(tDw@v6=exaN@EsW*uQY6%P4Jm zaWkIvw6*rGos=E4AUkOKIe$l*=aW88X?sZCz+n*mLG)7&?3%XAWsH?R8nx2Bi;V*t zG|%Qu&VxUMXNG6`&fw4dxw$#ZglEQf?QN7G`Uro|u)vjLi>12jzgs~PuJ2ITskHS}x@_1bo`>N>seZ|kNna2!5v zV%Po=i&kgv_6eT5XotP?ke!0M;KZf$^{sPYo z%;Y>s=Vz%uf4`j$e+JLBxBdptvRS$r&!i7tp78KOuPn9mVGsBg5$vw~RJeg1D( zlb4qsSaU6D&6UKJ*W#Cz#w^T>T)KS10Cm1VNabgG?FRh0eQS$Eui3f5E;&KdvjS$E z_Jd|3LZhET^9+AJ$NU-ArF=1?#<`m^-zHjVVZ$FmH~sBaK|rY@dH zY8tdNH}mKJgy&}T(m%qJ87Ug}P%-JPW!_)Qe4v(TUk#(4ss`Ou^t-6&c2d#lpsLea zSErSUew%)+yDu6!&H2|!vj>daJZj>3PyaMmcTan#1yh_fRLyjCEqAP$_o6cW^Sv{* zj|;y)&aHiNp4Pv?Gb$TM&Ja3@;2AJeN5Yo#Ms4+h@71KlK~*^<{@jdb+N-HJ9sj93 z=6!km`_j1TQ{Fj|9xn>Q-(3lLSAtU^<dI%cl?3P*NbnOF#E#NvE4C)5(Ts#+fA#)Gpk=>d%rDi*(pv zDs|0xmN+xbGkqlxFyjH+jTnpmbAOh}63EOg$7Tj*c|(K^ZvDtDLp?M}v-awU4(v{BAtAeZ_%Ffam zBuhC3$sz)VXXyaHq?sa{H_$YZmYtc*OebfWXP7ftsR7~i$HWYJE|j?#$jm&`Jkx6j zn&oF%n5i=$J#j=n8HQya6fnS#KA?U#HN)GRJ zgJ*;dk~bda5IxGGbdJHh{^2=^&|7(UuI>SJR#JR!;?KmKFe6&|nv5#_QIQCqKU5^(;SY3J^1`yhcilf1{^80#T*bnW z|J$OF_l5i3T?%@4Y401{EY7!7`!u}{eOE|ozUBUj9rOC_76IWeNTvZys{3=GEqZdW*m|?D~C6FV#o-u-i zZFPto3i9G@b4Q&Cnx7Tubk@%)(|^_}avpTd@N!7=n3TS2$}tazME4n!NA;H%<3E?n zl4JkKGgEe!x%%3?jY4?FU=m<%iDwz4n-n(~n5n~HBgxXd@%MP9C!Cv+O#k@r@vLmn z6(oaaO@q$rdL7hsZPawyY3j7o)^4Y(+g{(Gy`Et^3lrP+rnV#O`nb=S8@X^v+WL)0 z*RDGYo)tM4c@ZA3FQH_ItFmO&|J|jKw-*E7 zUG%4T4g%6I^MQ20i#-3wd45u!Js+I)y_M;exMN9YBQtrv7!%HPTkuDi@r{ThUOc96 zS;Fs?$*ZfAey>PcU5@i$%rfxox?+Ncg1i7bH!y@mE*ql$%+}G;3|l`nZ||(^z?oSA zvr*s3^ruQ3UXJN|eml8q;t`M8dzSuUY@m&Q3CNl|{8>Nvb4xt8a4qFWo~64rXlHKG zpXnY7UEKIvJmd67`qvUqruOZNbnJliKgx3#b^Xqo23<7tJE~GiLtUqxmadJiZaaN_ z8%SHvT36fBQnywAc3rnjoPOZXoFYMoa?V#t|!f0aA#bNIY z!E-Rp^NR~uql7gb1nKAb{!jA#pXGWz&GCAW4W9k0Gxh|pa_nwEc&5&PWTvh~o|Q!^ z9*ag-9#~hIysA2BHO=$&*yWd_7C77Y#Wrn7?21KIN1`)AT=P?W>K^5T=laLlP~D^K zpZl{kX*_InW}0VeU;jT}vQu1ab2XKJW}iX0M)ZuI90;?KB0 z`|(=TAEoh+b3?O2H{U;liRh?zmm}yF;fIUpccWfM)^xnOKzN2f6Q1+DpXBU$2xa?L zrtfic8q-NbN6ZuPd1QM`Q=ZXVL9K%juBWaO?LNISWyAFY%PSLCRwk}0M?WQYSwXn- zsKFiZ`|xH8E~!1^Mi%LM59w}q%y;Jby-qnnv$OZkI~O?jOu(GeesfOw%uVyQPw`l? zdfpgaHD$0&?#`0b-9mo;EB=htUN{U=i|Mf7tMO$hm~fVDru;DH+_FDY-4jW2rt>rU z+I)-{(Jw%emgZp22+y=dON_et-9QQ3vU#IfWkWVL%Tp7f_y#ajJa<>o>8z~PL0QXI zU9Xe6UPn#c4jNiEYMNFmYNqPyrYK)nnA-O4&~HSSzUwDW+c$slo~hGAofn+iwJUMW z$}5SX2luSLksH@QYIJ$^k8&Fjo*z-MnGPG${9H>iGbZaK!epJSYRSkbdfY$dS&B3% z+%ZUF){czZRi{7=;JGTLzABl_DanYYTFNs$cNg~=b4sNVf0QMDycSb_ba!s}_E!aw zq*sVLS?H%+40v-X=+&hV!ZYR1G|$g-yo-#wtK;- zX;IBVgb+xvlU3Ve5zDGl*I!RwUXi$>Dsg26=?^YL)uLlt6I_2Kt!_|>W;X{@qJl-g z4anR(FF$Brc93%pc=n&0=|3AhXZXxH;^Ppsb$+)FW@x%#zchV*#M+sEFK_&eXXeH$ zO*PH4bYKGw?!U@2)eY=Ge=?XbTa=#D}9Ta|2nrg@J2SQhgh zb9cBWUYhi}DExf%j%x?^ye&eN1Gi;Se-3_o2@5**foClCe||my@2Y@5gXiZtUQZA? za<-SB@OF2a+FCnWmG&Ro3P_qi!J{-lJz`!usn6*Ir9rT$#8Gs)%2HC1F{D z`vfC>O;AkNHh{GpM?py}?>cj2REJwmfU>+0 zZx5q*Mtu+ex#It|Jk#b(4It5BquDqp`LV_Dj4v5~{;ND2_EIwJt!C6$!??GmVGk{% zo*G6yK((4q2TkqvdU|b)jcqMWJ6TzDurzGj(WKqTPQA9znCmgs(Qn4=@P*4_R{rkN zzi;^3<@fTA);_%0fbc8@n0`P-PVzt<1F170#q)zRj57mcMlJd?-S37uH}z+UMYrJ3 zlvgt_lWEdsJd@iiWZM7z^~m?-v7fFbeY%$LFe~b8$flapsMLkMD#RMnkXHoeeTW<{ zE(B6M`##C{dy2e~>-8|(^I`6elGI&pvmES8EMZN87lkwo!KtQnl->sn=0Q-`2pOjiI59 zF=Sv3b+oYU-=>qxu#r0^O%Hcj7PeqT_@Wh4+S|?>((giY=$AWrvi)mGkNY8t%#6;F z`DYa6NL`Mapu3-0PejEGBn?SV5Rn7Iove(ynv=CC){)C81ZFAEbRqg!T{U#1MV^12 zH&A(w`{O#s?J!3g^QkoYV<}Q}?5C^y-W(lt2PY29Hr4ELC%4=4J z7bZ6xaBc9wb_e^uHex=H%t@0!jTEaX38<@8vc+e~%m$g?pyo6fk|hi`Z4NSJXZk^U zBqVP_p(Q(jM9~Y9>1GO3-)Jn;Av`m4`#29$F#qg&AY;yC!kIQ?X|WF11Ao>)=_)dW zx?@mZ-nb`triIB3W#ir&=yzk9&Y+tXDcK=)bV7dC*6)Ba9e6e}XlrV0)5@xICu_TI z=IzGW^>&@&7`1#|sLP6|&&Vhf_o^E1 zpCY0rG$eBxtAkW9=JRY9$yqmfEcBcF7Gn=oZ`nftf*l3vv$lezrnHy9)}aVXCB|>h-&kZ-4n2IW1Z741}ch3&iGTv@RA(fZi?4-Lc(S|Gl#*S z@hs^Hwlr1;q?yCupYlw%1tmN;I}9>y6gJPY**%r|_PJIRpZPPZ=b<_K5uu4tiW1tAr%Z%>P^x|${M%`V^-K9f#sF$kl z&dItvk|7N;M|b-;*2~bMW<(`!j4@F%DN1yRh-wkylR60=pkc19Or-U_B1yJC__>_S zj$$6^b18O$MSZ#!`RQsT)!>eNe;FIVu+%OL8w_3+huu6KaKe8<#j#yaa`!&Y-Ss%f ze!jb}ornQW&|kFw!|MZ0_-0lY3a330XiMWBfQsqK+(5=JA|I z*ro5BpXxK~;BLnxH^a~KS<>UCB1en< zEX#AVu{y?_LG}N?cvhs0TBM6LUtLx8yQ!mar_)JE(?&(JEt=h0`t888kx_f7wS`@` zw%z)*?liJpmq~WrXY?B6F>mDwzpxc!CywY~m*lbQ^G)2P!qt+~4R^_C93vTS)4$iG z;qnxO2QVzF+B;-e_BitgFM_gNcMeE7Y1cNX+s9a-zyTnmB-WidY$A7 zTEG}}W@5$H_J1N)ESb}wy4&aphCy!%!?9cG>BW7I^207AZOsf`e*bLH;~dY2*?8R* zc;53M)8qbWcf4ft&dFW3(sx&<@2pH)pB}JjM&ALt3fl5~riiOL@c8^~9o6qu5 z-iro%&L6dF?r@L!zxXWv&3DO|aeaG;@tRG#O#M&sEHkzNl4W83M|eh?`+v-z6^+TA z6bNIYx|V|tEC%SC_0=}+uBKzFfvTN$D@`qHBg1x9=C)m0cNx=b@Z|3OCfRnK-nqy0 zp8YmYn-k}{bCcsNhrz=lw{Cu0kwIT7Y05K#1hHRQAeQia>o`7f%4?$AY2UFchQQp6 zXH07l)!#S>Q6ytvgA%F89iU16UJ?KGI#x1D^reisZzX~G!`0{ySED|Zz>veJp->Fb zK_EGl5_k@Ob}{tHh46dXL1#ip>UfyF_ffXb<8%Ix&iX$*<3(N?o4ND;>D_ludfrU) zs7l**$a~GyeuH!swJ}`B;_~HC;^1O_gN%$4e`b@GA73b(I(lec*pmDx*TTp}m%>+` z3t66r*ADv6+%~7XmV&&H>=K1Pi?Dk`z?L^rRo*mXP{{9NLf1OQZLv?wgWFJWF&X5SX;AEG{m)( z?xt3K2lSgTyx(t~TG`pPvh8DQH>7=snZ0{$96i=^hLeZGtffPLT{C*B-=ZZxOO~#k z?zmyP{r!tcIM6lRMKI1lw4iOdL7F8b=-$HECmF_&?O)SflDZqm$@%Wakp?0}Vgw0X z;wJaFC8DYpIOtI#Ihl$U@Z`jA<#AujV*&G*vRGQ5%i>71KuCrsUqeDhVVT(SN30kv z4t?K9GPMQz(!ST1!d_kqdtR{b$%W8I`JokQo@xH`D~@?Q$_aXu?f>WukVfQihf6;= zv-{pD_nYb1`nYx9I;WxS?KA|M0=@`gLyjw!lQd9BPXs)}oaIGgXNR$A-m~I&E{oed zHFEvL&<*zcSK5cK8aAn4J9$jyN%98ana5V@YH7CLb>0d8rAPc0ANQGa+nX{oR z#?14NJS!UaR5tCSW)o`uWze1Yk1C@>XXd3s@vFP2VegENoMvm(}WR#8VMB6qi z#|>IEu;=`4?N<-%AL{IKbjuD;d&jlEjPY=sb!?B9&yr={OXk12dITm6fN6#qogn=0kE%QtQGm|tJqyh8i(&#^~MNo>8re%ufqEIYm zq+dSzu1J2no+zmIyqnsj97-KQ7tLK4sU66MN=o z1}w@9U41rq{i#5gQN21LrhsRv?1nvQxDc!OTaT`Xyq2ZyU3_Bi!ps2Y)Bf{M`8j8x zEx5<&nAhwSpZO^}=gu1Ui>iVOwt28v@&slMt^)kKJWF3BA$tb=(VYJ&o|_#8N#&V( zn-5jcX!K;1HU0|EVrGdaE0DRMWH8 z(=)Kp)9!ApJKS1-x}DjAp>0=>?7Mha|5YPK?w;-xw_^RtZM$5@Oz^Ouab)Mtn9b`i zrG(es!CoV(KtXvj!!safas}4HK(s|mo7b{~b9DU;JRhb-EV@yo11P1Msbk=QjM5Qd zA0xWhKmBMTxFY^Mjw|?t7LU3YWf@;dkSNNA;0y*OIsAMy^{iX_&Q!t|C{3hnH4S zJhQnd-6|qrnZ5i6W~ur;x)J%gd|qxY&C}^0R=;9o3^pPQ2IkLvEK3Zn>Jctu%gfal*EXi5sGJ z&otH35y~kdrXV&@uFh6h(DZb%KNB%OGh}W?$O4*YzEusm0LBALWX2NV<{*(|Sd{LhNG}XFNzO`*>z!p?nr0a5_vNTJ z3^Fs%Eb77_OWj7Qwk&M=!nQ+=_GC95L=7PQIOj}HA4%tt=qWpTS4`u2I)-Pa@=R}5 zq(4OlJ!#?YwxV%w72_T{My-tu&CHC9j7_`hTMp5&96*^FArr5?Bjb;Mv4K*k=OH@xTgQrVHG6^FY;E&bg z3LzzGe;vu#V4Eu3rPfi`3F&lA+cl;&DA5~}$aQb}{vZ`aVm?vj4*HPz{tB8YG4C$# ze_a&y>Qdy(OOY=whQGWR^&l%O&40!DgpJpa?yN}Lee<+;&Dp(oQ0~a`eR6JJZiM@Y zF1G6O%6Q>6pRAgLC-eDSkw~P1!6aOXMI~8{ud;OXF9k_Hr3d#E9ds*A++3Eh;cCL> zg2Z*(R!`MeRubTSnQ}ZVd}iaFRxFmOzCq}wd1oS4WCkxi6HNS>HfNgWlgQFu^G@uU zcg$;k!mh8FaQY}U=t*u=_E$I{ry#JsDXSNGqs2;4_dNe#-r`0emi~gpqhW71kKVqok zuzr(94Vgamm)S03UDixmw9RR8)cTFNQ6cxU4}ZIfuFCoPNAT)%4G&R>M%fvSKj|(n z8L%k>r)`{k65nnVN+OhM$Qs5UCA}DXw4Mz1H`bytwjmKUjKmDr(R-6{Ck1;)X{t#D zkE}={`fxSo!aS3g^}R7BzecBc-O}l!k=CU!<&(x6$Csj2zs2q z?@4y>gLAt`tYw(lf3cY<{3!SJhNcSFlXY=5}patxKSld8nSug=l}UJUUv$K6TVZ_g$BJ{cxDrbiEt1uX;Y&)AOwx!nO}Grz6ybl$GgY8& zU0iZ#`whUHy0JWY zQ+dLsviS99qgD+=aRa`LQZnHg*8#*L4tLam&ZqXyITzw`HrVB7Jg0liJ-KUk+O8Rg z-4+CGoYU9N2BUp)EQO|dLlQRr6Mtr_w1PM)))J{U&eRc$rt$_?&4#DemaEp5r{2i3 zY^ClWo&Vb-wG=xsl6Prn+vt5Et<6-laOMrvta7S4j4E(Q4+&E&lk=@ti^?kt)e* zI|!>90do_c8zV;y&GVb0Xi717lkCM<_iL$pK=RXqh^GZ%FY@=j$qRg%AM!Le2p#Y% zNBve#8E>klBf^*{(lc8~s?9_Kif1zO%x7`CSy-kAY%V#pzB*+~`N0jP2R4)?Y`hk? zA=Q6*r?wU%7Ah3D`zM(x67vPl;|FC2&dUjM&JJ|RYU0l>czG7`2K+hQV_y0$r!@EJ zhjuum?wY)F!BkTNV-8#Kr#v^AL9$@U<1NOPkR);-JS*Wah@BhKH)c{*XgQTOq(G-? z#a6ZC0%^5Ym=UFt21ssCWek#^aU`VunWNE;EfLumLqwefWk03oLD}RiapoWM2IJ2n zY7-qk6%2Z*m=4sk97@Qv8lr2_+r-4u%0#oRsjji1rJivobBoTcE!wuRG-ze6XJOvP z$fCEAB}bc9p9sE z@4?-NIS-q@dfconlV|OjG3&sl^~XH7zPNn49^2}WG|1X63Cs<^`v*^^>BaZWF}{<5 zO<#~SR3lwC1`j50H1lWKzTx-EgV48%l&|HqeUI~kQTmAWTsgRVcO{XkfQO?WZt!7d zgQ{tuo-9zn6bFZ;C}0Uj_3U;&ZfD7%P1PxzuOHlaEonn(!n$kmYlF8;G0;-Sf&#uA zDt4G*Ca<(oS5m8|7R!MP1r)e7RPTJs3cZRMzIupBkQGrgvO_Gh$LFuXzY zjCZ^WG;ASRlIiFFglFvU!rCsw6oCD(KJw1)3-1)Yj0(2 zZKi8tWNB>CQ`c&cuEh{t^TE0nSX|IY#i)m}K{sr%Q#0ZWep&$Lya zg%e%2IxHX3WpIy<{pJpuy!e-?>&H8|PnqsN$N8}Pwu%njkBi-M^x(jwz0w4o;CPmKDYA`-TntWU=$9 zhC6?WXCO^hm&22(PloFM#Ghf#U&`^$paV3?)L}3l$3UvAf%Z4n6yRl8kqpmoive&{ zF;yRanoro4<@xdXeb10L^7rON?wH-bznQ*CbDn`T2a}^pJU&L?l$C|5o99m|PF`J} zyrv>~ZP|hKR};;AVLG}ROgbTrMCl?{aoxr2rn-#sl1dr}bc z^nB3c^P!j{eUKY^VE5|&ZETg~)rA5j0np_UizXQZlcK2C36;RPkf)-ntR1k~xjg0f zs^qohiR;P|!SmXZ_%-LkmJaOMjw&2eJw)o-AeY1bWpIy^!LAoV=H>;?%?WgFiD&1u zJ@e8$=TMQu>F7?!!)^|T-0V}`CIIZFJY(|)ReTni$w6X}Y#}Fa#ZqX+Qn2R8TXEzq z<>XDN%T{Jwc}Pzn*2NNU5no-*RhDOq6j?$gwor+MHtb}T<1X{LYO;nycVQ&melWM7Gb^zEMO$ZyyN%r_LY>+}UUa?IHuXAlC zA@#O3^tI&;d#alB(Xtw-V?6{&Ym*2uKuxQo2+Q-iSg?jQK4Lak0WW-{nzKT_SXb4c zqq<3Nb(3D|#@LV4SKXwKs!=b54Hdo4YPf!7*jY)hgHWRlU%i!*ZhK8rI}NLzX03Ys zK4syKnaf9Y9k6Vaz02^)PJ_oS96MvpgjwD$OH;OQsXQ3=z4}~34R~%08#Kv({@GZR z#+z2CNq%W^CNBe`rj=x2md^9jopHJ+j{8<<8j?{ZbPVa&1Cf2XRMH^R`w&&51J#iv zITOXcDT#$SUyR#y{mAau7o%Ta0?+8MM7$`BM2F@1g?*3DM?A^jd*!JAW~XtOi{rrx zh!ifXA>$Ih8EK4<3GcrtM(LeNqQEl^sZ z#ogWA-Q5!sB0wNPi@QsM1eZeFTcKX8(3T3cm;0^XIY~(UzVG+{p8xyoXYO2X+oyfI z*jc~5*IIiy4Bb7CX7)akf&F;TvVBT#>{IX_lqpB|opZYFnB8Ujtj=3!blN(-{ae%8 z{}Imw#wdbkpf{3~IYwoU(wGsU>4QmE%isczSFe|VVT;yk(U{F@+N9E9iEdG;QRL{g zN>A- zvwUv5BBaal452={D=^82)^Y~x2*En8km^=z7{gedRF7N{R)BQEMl@OX1{6`{qu%e`?#a503t?@eE*>Az66|{?~YxHA}zV zB7!BzN0m*=55$e4Fz2<8uN07*o0p*BU-|G-!9#%g;@WR6uD!W)-kG)I@eF);ZZ+yr z$*ONk@*jYNoL}|u%yRVS&yHnejqlpJc4~-Ar~qa>0F7Fm3FmQ9__xf^X1z{dJ3amQ zx^cI*AWd}KjiS--5Im1W#@F(RJtQZKTd}g41#)I&!D!qpJ8wwq1380Ff^1~KHi+s| z0na^^{owBT$QSLlYi=o?x6baeWoD->GdgaX-a)~$n!#oe1y70$X8BWN4AYpxQEF2p zLh5wJ0L@4g4f1cJb#{Z+Y*R5-mCizt3{92JtkPQKLN{i#MuUbisTq97A7EE$fM+Z5 zD`LwI0ilILOuH?L#+eDioD(&Cs)nzMPvv%%oKf)SWTRq#MwhM#W_JQGyE=CM zI$O|;5HL@&)05~9NqebMoxY7a3~1JVM*H3klWV<}`f|tm?c3FD+P&^;g%c*OA3fxw zJvc^xob3K8P>6s0Uf!SoZ}2QPXChUqh-YPi@*{CqVL-R)yNl3{X5pF}kc|5LRQB7e z$9#Nf`Ga$7WH7IOB(Dqam8`yVHusy;%W%Q)lfxNv2DIqgv|d0Wct&T|>HubfXQe;O z7oV*RWkMoHo5qccH%z*@X@uOIN8c!%bhT*2rGf$DdN#2d;LHN!fFTP}br?ZwWBmTS zi9HYG^g(|7K$vhi*f|fr784h8O)`}P|Buuf8U?~h-U(6`5LA*fF!z_C;`(p ze|3wHKQ&S-Q*2%*(Exj&2O>VcZ*&%D1nT(PWF z3GoHIH^u2mHVZL&dzh7vLx7S^j1~OJm7=RQf8n)}%{vWyqh00jO7&Cfw5auF=lU(1 zrBu%vG8{Pu7jhTMl%wL}@1MU{!1M2xga6o{x0LU@q2egl-IexdjOj`x{RITi7omm5 zh0T@UTr7Basqn#tbr&~Jxw2&%-hhuv3ecG!ozH)CKJS~ed3Vp{-#MHA@C>BUMepy< z9NXoM{;gi;tTr8O(^6IqAsc2iXRQt|Jkp=_IxEU%unz9g`OL=I*ES9Xp05{+oPOjzxT4R=%>OZ-HH=TE50LXHfV448 zYY1u#ehuTIXvv^;8g#5t%NjLigT`V|n;A70n#2|kQ6SnZ)UJ$*qBTZZXJr_cGPx+T zpSJjPwh$c-LfNAjsc;aA|fqUkp4)VR>Yqot2M~XnK-R3?D;%x5Kjf;o0d81AJnl^~&7&{I-t8o&S zP-yZbe2!-=>vBr-r}i${GUe(<1lEnZUO49Zx(Qd-4Li21cfCq6(A2>&g%+*T!gi=L z>*!VuYVTe;?%>LP#hE>eGkc%>FZc%f^Y&S#En4OqK0sP+@T(cWhOlCno^tASc1B}` zmK5u7lZpmOkP8?lai;ivM9YkVqF61>>lhcJ=`|Lw+8R{bqM$@VLBo&5iVDg6_~L|e zBTnmxHP|9dMz00!TFs!n!(NWx8fes%NuV9!v=FBke=~pnU*j3!x4^RkOMG(Pnh4V{ zSUe^(Z`7O3_;+A%ur^6cnL(5^dI!>wcwbdP2EQQZ6#&UjKa7OHb1E!XtPqP}M$VJS zy5bFNxP^=5yvZgZ1|@l->nGRl_j=0|KhnT_>CvezUTV^^&Ku2Z)N5Okl_c^t^|j;Vc4ipAteQ#AuBbgDW}mqxJ&cB z%f=sC(f@Qt&*F@pNGkYm_{MMX>{ja~oblCAP7nZEi-nGXQ8SFnzz`&3DGtV~q#J-{ z;FcEto-taqj7zdjKvznIWwaM zN$lV%YDi}BTU%%G(9S5dXv{R^L|k%L0?Lg)h4kO|XAC!Fzji5}Mf7I`;kr`HY=EL{ zpcc5SZ8h>16Q{;M8O7*~qQjNKd8!EBssOXgS4{+r$zB^S?{was!ijNC;8~30-H8r& zg4r2m=3*W0N>(w}=!`S_n3`xF~!<^;*3^2Qa zQco)H3^Onej7A}m)lp`fnZqbauh$z*2HL=qTmr-tc&bX?svb`jkEb$^8J#DW44qFk@75nqE_lR{x zX3iVRjVh&J#>qAr#^s;j8;E_zd;?SH$CuYUx|sj@shs1hN8Ub~_vqrfM;F!t&yOyk zIp;nq$@!*a<$ZMNlH9xJ^MU8vCv#>DXqOrlC78_=IEG9%l;#XY5DJinJPD9C>g>&5 zt#@+c(2}>to!>b08pt#FM&XF!g2`iAzs_TYh@>vLKO?#sGp3}_kTo-g9m^elJbys( zie8BM0^c~1(N~^t;1Uq@&t$%#=r_oGV;-4r0MFZIb&>H*<{L6rWkO3*IS`aU3|U$k z%sLHbi8d|m)ZiGIQPdjU@F{A_k_t2=i4prjQfgZa%qckigNvCcwB-s_8Y6@L3`mz% zoZc4BFcNOZ;6({{0R=-l1hjZUI^!rIMaLU~9x+0R5@8x)gMpXGuxvMB|LnJ)o zLNVD;`>OH&s-nM|OG=UKp`3v=(`H5w--Ow0;caH8-D(wBli$S|j5dc5>yl$PL{GZg zQ`zlG6JXxwq$2RejyO9$8pOjU##p&HNs15plLe$TvY`SW;gOFuX?ozdL`D$C)Zexu?Tq;-df4r857X9FS z*4d3yF7KH4;3Ce}uO(Y=BJ9sWJ;W!5&xA#z^6sAlo-<|)ZkrqygJ%z-_+`$FAK41i zApIGIUx#GW!Ptg&d97sAn364%&TX1_v2Y4BNbjs0el&M-tJ>AfP~jup2>%EEEN4a| z8hXc)(MNOpAIl$jBCF5w6}>UvIG)-6Xa*$E@Tc@uM$qMW-Z`(^_PM3Z8O>RlZ&1Jz zQB#8zqx3p8BqjKJv*^&b^*lz+WaeC&Ap=PgiX<_jDuxv(POH*WR=>wH>DZtjT5LljRth zbkUpUkt&IF@vIr#{Z(1;cdgo}v?P!h#B)){VNgHAqD z5~IQciIwAOyj-PWv)V1&z1X71i?8Ml9el5N)4xAF_Ung7foB-6p4}!%1%HKSGNY6I zS*0-k05gs4M8jVizEQdgM1V}WG*p>sD7KU*FviLjZ@6L=UFaY2{P=SAk5@6`KyzO8 z{(%K2){gt?+}ekifoBZvp5yr&3^z(v-GgZbZ^M$+1kb0I&KcRQQdpc5i(sUN5+wf# zo(*`9vCgb<9g*&JVdI$d>qlQ)H}+D&h%0M{Y+o|AN<0bBK$@t6XFLqi>wCQM%8{%A zN3(k!L1p!p3nRM$GM*vnFU51|2zp+(9rL=D;~8Kkd}DeCEq>gSpZM50Lgr_ov~V?Y z^2WriF?!X;fE-;OUK(9aw%-4Q=ifAE*$=DWxlD`%FcXO#2UN!xtRZ^JYE!AqcpE}A zh;1puQI1G#SZFAel;@#Tz9lRLc11iZsHQ#D^qwjh)}cR_;@Mlp;Z3tTA}x$4*jUkI z63lkq%$pb|R$3fu4-auhNY=zKmy2_n7*3F4`2bl0BFxToj+bIMF%r#L z;DQ{Ak6^h7t24^RMX*A==uQN|wgb8LIqYHbVy?0FBdSez{$~P29|E@om<5^CXAiR1G^ux+6S;kluk3v+yZ6y7rT*u5)?sXj<+~Nb z3YvD)bU?>ob{A9|LkO73rHL?zMgM?j#N!Ay?GZ+(JAh{w4s$2#Txk{0b1QhpCjqmoDvEYjXWUf*X(Pyn z8_`CotdL-_2h0p_)0zaUIh40acB_RpQ)nq_gVkUP5$(}ldvcf<=@qPu&1&`GiH9Yi z;7fIRQjh`-@{AS@xS|ACtP_yt!jPIP2SGh%PNi38aBLBb?4~fr}LRNVgOn z>P^6Xw_3^ddN%4bu|vlNUE39m>VG0*=64q$Ou}K5GUoi(d;^*dDC^|SAi%8n2T3y0 zZ}42f>#ew}u-7ifvl3bGS9k{BK!U+{7m<-Ww`9XyLNl)9eRC=6n+vPU@%-?7F2OU5 zSLasUKbwE=%&I%5Ge0=CWZK{k$&oR{*2l< zy@Q633Y=4S>lnXQAEse2e~wV2$W5yd<))R|2o(n@S^r!bU=DSt0^{<}zc`&)s^{01 z9vmcOL)JnksCe8-iDxW+Nu}jAI&8yr$P~dFL5Hhdyn#)W@tjJzQq^vVkxCD=mGcb+ z)dp8pgH(-nRRgN^knV$Qfci?woET*@a4c;RX+7?!g*(k2tHlCa5Lgu^gcKt=Y%u|$ zQkWPQ6hynjWRh6YlPkM@DZD4eO3qs0F-RIUUW>dd!6`*MxG=jjge9nsU>#vrTfpIr zmRuz893U5Y5E3MxM~PyL#}yaiuaq2Ft96|wGkWyQ=-chB$rB1k3_6#;;Mad0DVs&Z zF#8*YQiWc95O{w20l8@s9b7}s@ADVMHe|~&57dMVS zKaOqS^skHazQ4NuTlD9P7}JpjHzv<`3G})tSt950U;{GdWo_ zIk1>0YtFyr&y>-ox3_3e>%{6&xGQmk2%bk`Er|YnCckg*ruFprH=tFkKnlQikqoBM zrpL!_nLqUHtlq`heT%dEVUu!dML*Qv;<-ESO}sU$lsRvl)_(oecAznT`#4sTtObEJo+Q=J7^kOwX_KBV}Wc6F6REI=T&9Mr^ z)d^mT1?ynBP`fk8qBGk=%x1667L-6#0Ans3OhXXxJr=_~UW^l@_z+KW?WAghnl)e8 zv)jh8llM%Wx_RQTM^~^SQKlRi-~9=mfogJq{^NsBKivQH!+p>2FhrIekVGP$ z-^r|j$1?lN7Q)~1=lR`t%p-VKXfwc!DgvI%(s7B$iiuPi!ifxtG-NQ1kkW8b$T`aU z^ZyLb&&^iaKgBag@GPozn0@0a68Hv|>3Eaktc(ta-MLtutCH50qIOmLD?A(B=_s=1 zcBRqY6q6g{wRm0#muy~9XAu~)moWushaXx%$|z|Vq-JwktN}EVQ5)tkMhmt?mo*6j zQpRd@_`|%3ks;|Kj^YCdVJB`uS@nk`}oMOA07CGJo=uC?#kbW z_yREh^3lPkw~s#g_}DKW?nhF`v-jb6mGO+^y5Hehj@>Bh%m8yCn)6TBkt9RvFYrtz z&+qP9R=j2$yi`P4SLzvr04cw;(42pR=REAY@0`tg|9JM~0qr8(0%x!o{u<9vD^4HU z@fc?u=B`i%pG_(XTX{40jIME z{EzWGrELW~L$(oKDib9Du7GD5%%yzepYa@5VOWRn60k($LiDo$(g4U(o1n z#I6H6g?&0htBh#WGz^wzA0xyA$&{G>2RsA7l?^WP`m?$#8(qmpF%e{dH;Hb>;iD}f zlp#z@N13=dyD!S_4K>)jI$TnOBt_@eP?A=vVI67Im{b!y#|c6- zFGVJV#k`o1(!D{GVf8z#=-O}3oN1q&-SzA3(@#G>@{}~;!@%vc+r%mh?jh3;l4^AbQ=*L6DRy%H28qL^U1QXlb`b?^5f0 zYE4k1j?-xpDQ%KYTTQL2q1E-{?Aal{7Qqz1JIy7fi7w2a6ET$ICGZV`XS8TQn&ZM9 zjt~nL=q49{EePaSFndE+=E&+ zeD6TvFYoUoNlNc+e}+iL3b`@Bv%)kWH&RL-&?yeVbO2)7e9SXVl5efu$p8L?j^}X>sp8 zi+dr+ZZ{G0lV!@*+1)nJ=)7@S#|=|Ete?`Za8jwBU+K~^uw^0*;b@s376UrcnalmK z|BUB&1=5r~4yCK$??$gyvk3rmIi6uKv@=dgV`dRW0z6}9$GG%(Wf0;4=0WLg9-6OY z5L1mJxz1*kQcOakjg4l}7|m`;?||tgL~9L_cPtgAp~BU=2$dF}Q7T=SnucOKOlJsa znGlWMPniOgAwXFIkRNG{0j)7w!=!4d7is-#dZv}$*ox7QlN`Aosksmu!o|3;D-mKq zCpaOI7ZPyj3Ug+(VvY==G0g}yo85ZMtV}Ki%wQnEv%Gcz=A$vMc0d;5iuC(pLwyN# zVqY21u=TObMYm5Ldh*e&PtToPG-}xERnluj#=c&q>X`0b4iw}UESl4#RyA-Jo?)Ci zqX3P#mG9iJ;i3FxKixd|?EO6mX_Rx2ln3A@Sw2VbjLuvE%$PZs;+cT?dLioZwRPWL zUHjd&-0!XyKDxZ_}B(>X)l&K`O)yFco9Cde}^-ZFn) z(hGRrE1SEaeBL#u+s@ftx6JIaX?iE%dHt03g_GK@ozS{e|EvT)qfwI0 z*zBRK+2>$*p0>Fti%VCehin+!C7WTiR(6`qO6`5Nic-(3Tk*M4_>CGdQ&WbNs~neXpi z^xdVR?=P?a_F|E&)&D)7(Vq#J(VS1`+$+unp1(S}{HvqOR!#0)Jv_>V|91k+n152l zjZ%ta3bD`FbTb%-4rGctlv zO(QQ7LM4Va+09<3(a$riq{GIY@n~p|S{KkzJ`LqnQ$Cf>r=q<0uF-iklwU*p)f$gl z&%@`1AA;DSYt59-!q5%}8<1SFZYf!G5h5W-i6)p7^e(s^A=mb)wIMoPXS+R<p*S z*50LOil#j%Av2BduM~cFc|F+)k^mW4U**nRf>j{l8#0))khyX9?VP(Ovc5i+aeLo_ z`2!kO2}DVFYU|LPA?Y!q6g(p@7hga&9A@kE-rcXSAB|J6*NaA9E+TlwjfujU{lonN z8nTXDzrwm3YEcSztS0pCqBQ5?+##n{4my=RnBY09-?7XAu&5l&=(B$*z}#cs0x%7L zxht3kn)CLVoq^{K(>lmxgW$Pfd@IE;_?&P2MSm`*9KYeu6}SiHbvOW|U>JNuS60xA zY8(kbH4+TeY_t}18uBEZP~j5Qe7xBbWHn}|)@ULcRN8EmjP^*gL9%FI)KWWD8qB3# z8a;#~0#tx1gG_M+1+~o`kTnMBZJRbzGSvFuWL7K=JEiRMQV`W2}jxekau_YuALky+MR3E$$ z7U2$SRy zurs_>XSQn%7;_J4_3GX8TmJLj&i}l-RZd*o{OhgFzuw%eG-qY9Q88PiBHvJ!gO5O) zudV^4kqL9Ua0=8%kI0mo8Dd3z(a>IA$ez@fTHoXQ?_GHbx`%zj6gL%Gr8!1A8^ z$jw2Vwd%TSZfDfa*`2q|?7VFT7Tknv0MA8}+o3uCmw46~!<8a_*a{e~_+1%91J5*} z&1lXslr0*iwMSBpSlSk;F+!LsP{vS%Z)nI#Ak3fRET#}nZ2=zup5e^GgpOk*m(B`6 zN-C90rFN^-K9$<90(7;06@|ZqM@_pll&CQXI-AHylG(%CBkWwfT}bvhLp*wmTdgJo zKoxP|>g0$&{5Ii*Skav#xzj`s&KalSqJ&*aHnKrA?Nn#R%;v= ziUFNpNO1A792;pdd2A*xXA6k956gv0Tu{QqT8sequsH&>L10XR(c%W4K|C;;c96xl z%(3w#6rvnrr09yQ9GTqd5-mT-S?OQhN_*%U- z4I8v=(x^jnY&9EgcN(pd%~mPk>Dr*q$#sjLzPs<)yE_!}3?vgUzq1KQCSaB)8-K(z zQ2p~&q7=oUpNE(8A6+hZaIxUhrYSeJE&A?q(WA?2Q8J#1svjzjhv%U|BHNR1&gEgI z@!;&r2gOQceczN);u-E6=5?F*#M)#W*MGAMDdeLn(~ba z{6N&lg@!1JC5riWUM6IyE|M)4U<)@`jwv z9eg5p;PD)SXR=0F-uDQJ$?dUkY4_cWy6j!hc{h+erxOaEZWv${JS)vvA381H{L14`uxM*SCMd-AK;8qq&NYpr}VL>ER!l!1*jI%4&<2=Ht88Z{cb4J=wi z#TiYb1$HKDip5iTLj4LOGpX103JpLL9b zF=4$xC(}Yr^vy|wdKE35QL=N@os!)@-#YZ`d%K^#yG_Z$Ed}!p z;@Vc4v&^5B6fg1;EbY(N*Zq900ENuwhnE5Awf{P@^mM_PyTygyUoIjBSUGo*#BKo0 zL{OJUI5Y4}9)LObP9v%g%{c>j{^}_3ob|=wtScL)^=y!kzy&ON2b@+4o)x}9)1`Q3 zD8mcsY5P~<*8K1*>&9MLJNEM0Q5Ora`y1H0dJ>%Va&wmPOtvcY>$TDmnGP^xQU@>} zTiG9A#v2fLM(p#!B|Y{m?z(GX=RNZ~{SMDtr{i#&JlUAsP9Ym>#6k_QC1`($&CLg6h0RXxPVSjX`O1yrPA?b7Fc8gSkzGNtFhR` zPRXUU1{lcj9MLv(V>KnJ44evo8bGKQRcb+{64V+%O@QH7r4!Y(s53el9*;r0Ez*Xr zE+iVoN|--m#|_zrS*l`p#fdIYh`M^Ea<@&Ewt5-9%R`sN`=_3YzdhzIkcTfEMuj9W!kN58WU*FyJ ztHPYgS`dllU>ci#c?WnVA&%h^F37(Rf~>deMZ`; zLn49Jj$|Z?HX-i|Uohf8b2jTutsB)pRWtzxtILJsE)iMX=(B5vZJ$59T0|JO3^JZc zEEq!TEHpEqb%Rq_pyUj~*cr5$;2C4O4D{!IhoPxk+;b1^O)TiTXI>XD=N)r8?*Q4D z(dn(}o!^?)Y17mW8z;A4Kd~Iot<_|vQ9jlv&tt@VgRE5KVI3ALKrAV|2gv};6bkg> zQ)h&>->qhVI7o^>c;&bP4Kxx~_^^Osa<8-W&>_H#^mQEAqG6wf3M=J%AwLB*#Ks6yIR9Sq@>cqKW^5ucGhp?Am>O%EWb%gGf1hJ;4wJO=0b){RjVsb za=Al6ZF#q!_4pYUlv~C#^0lEJL@R)g7`X%{joz+fINB)D<`BjhMjO2}BSOj{QuZ*7 zIoV>H&Dti}*=W1X$v9jF!DV*(P5v0Gzb5BuE4haGe3OFy*>RB*y~&}| zIVtkbi+~!N$t1Fv+7Yr5B?-}PDHhvsi3{@z!BBT-dSq1n#I$~|v{>GA$nFV~w+

O?#tqgIAJYXkNF@lBpv#w)S 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 Am;e9( literal 0 HcmV?d00001 diff --git a/test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000389.pt b/test/resources/nasa_13013.mp4.scale_240_135_flags_bilinear.stream3.frame000389.pt new file mode 100644 index 0000000000000000000000000000000000000000..a1562238905b4b3fceaffa5ec2d3240af3587ca7 GIT binary patch literal 98868 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 literal 0 HcmV?d00001 diff --git a/test/test_transform_ops.py b/test/test_transform_ops.py index 8d1ba5e53..036bd4c0e 100644 --- a/test/test_transform_ops.py +++ b/test/test_transform_ops.py @@ -22,15 +22,69 @@ get_json_metadata, get_next_frame, ) +from torchcodec.decoders import VideoDecoder from torchvision.transforms import v2 -from .utils import assert_frames_equal, NASA_VIDEO, needs_cuda +from .utils import assert_frames_equal, NASA_VIDEO, needs_cuda, psnr torch._dynamo.config.capture_dynamic_output_shape_ops = True -class TestVideoDecoderTransformOps: +class TestPublicVideoDecoderTransformOps: + @pytest.mark.parametrize( + "height_scaling_factor, width_scaling_factor", + ((1.5, 1.31), (0.5, 0.71), (0.7, 1.31), (1.5, 0.71), (1.0, 1.0)), + ) + def test_resize_torchvision(self, height_scaling_factor, width_scaling_factor): + height = int(NASA_VIDEO.get_height() * height_scaling_factor) + width = int(NASA_VIDEO.get_width() * width_scaling_factor) + + decoder_resize = VideoDecoder(NASA_VIDEO.path, transforms=[v2.Resize(size=(height, width))]) + decoder_full = VideoDecoder(NASA_VIDEO.path) + for frame_index in [0, 10, 17, 100, 230, 389]: + expected_shape = (NASA_VIDEO.get_num_color_channels(), height, width) + frame_resize = decoder_resize[frame_index] + + frame_full = decoder_full[frame_index] + frame_tv = v2.functional.resize(frame_full, size=(height, width)) + + assert frame_resize.shape == expected_shape + assert frame_tv.shape == expected_shape + + # Copied from PR #992; not sure if it's the best way to check + assert psnr(frame_resize, frame_tv) > 25 + + def test_resize_ffmpeg(self): + height = 135 + width = 240 + expected_shape = (NASA_VIDEO.get_num_color_channels(), height, width) + resize_filtergraph = f"scale={width}:{height}:flags=bilinear" + decoder_resize = VideoDecoder(NASA_VIDEO.path, transforms=[v2.Resize(size=(height, width))]) + for frame_index in [17, 230, 389]: + frame_resize = decoder_resize[frame_index] + frame_ref = NASA_VIDEO.get_frame_data_by_index(frame_index, filters=resize_filtergraph) + + assert frame_resize.shape == expected_shape + assert frame_ref.shape == expected_shape + assert_frames_equal(frame_resize, frame_ref) + + + def test_resize_fails(self): + with pytest.raises( + ValueError, + match=r"must have a \(height, width\) pair for the size", + ): + VideoDecoder(NASA_VIDEO.path, transforms=[v2.Resize(size=(100))]) + + def test_transform_fails(self): + with pytest.raises( + ValueError, + match="Unsupported transform", + ): + VideoDecoder(NASA_VIDEO.path, transforms=[v2.RandomHorizontalFlip(p=1.0)]) + +class TestCoreVideoDecoderTransformOps: # We choose arbitrary values for width and height scaling to get better # test coverage. Some pairs upscale the image while others downscale it. @pytest.mark.parametrize( diff --git a/test/utils.py b/test/utils.py index cbd6a5bf4..43f29cf5a 100644 --- a/test/utils.py +++ b/test/utils.py @@ -430,7 +430,7 @@ def empty_chw_tensor(self) -> torch.Tensor: [0, self.num_color_channels, self.height, self.width], dtype=torch.uint8 ) - def get_width(self, *, stream_index: Optional[int]) -> int: + def get_width(self, *, stream_index: Optional[int] = None) -> int: if stream_index is None: stream_index = self.default_stream_index From 3a2df84f16bd4887e788ad473e9b7602586583f1 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Mon, 27 Oct 2025 16:52:09 -0700 Subject: [PATCH 02/14] Lint --- src/torchcodec/decoders/_video_decoder.py | 8 ++++---- test/generate_reference_resources.py | 1 - test/test_transform_ops.py | 14 ++++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/torchcodec/decoders/_video_decoder.py b/src/torchcodec/decoders/_video_decoder.py index 5917abed2..5a29b8b19 100644 --- a/src/torchcodec/decoders/_video_decoder.py +++ b/src/torchcodec/decoders/_video_decoder.py @@ -103,7 +103,7 @@ def __init__( dimension_order: Literal["NCHW", "NHWC"] = "NCHW", num_ffmpeg_threads: int = 1, device: Optional[Union[str, torch_device]] = "cpu", - transforms: List[Any] = [], # TRANSFORMS TODO: what is the user-facing type? + transforms: List[Any] = [], # TRANSFORMS TODO: what is the user-facing type? seek_mode: Literal["exact", "approximate"] = "exact", custom_frame_mappings: Optional[ Union[str, bytes, io.RawIOBase, io.BufferedReader] @@ -435,6 +435,7 @@ def _get_and_validate_stream_metadata( num_frames, ) + def make_transform_specs(transforms: List[Any]) -> str: from torchvision.transforms import v2 @@ -447,11 +448,10 @@ def make_transform_specs(transforms: List[Any]) -> str: ) transform_specs.append(f"resize, {transform.size[0]}, {transform.size[1]}") else: - raise ValueError( - f"Unsupported transform {transform}." - ) + raise ValueError(f"Unsupported transform {transform}.") return ";".join(transform_specs) + def _read_custom_frame_mappings( custom_frame_mappings: Union[str, bytes, io.RawIOBase, io.BufferedReader] ) -> tuple[Tensor, Tensor, Tensor]: diff --git a/test/generate_reference_resources.py b/test/generate_reference_resources.py index e02ae9d88..18a0183b2 100644 --- a/test/generate_reference_resources.py +++ b/test/generate_reference_resources.py @@ -133,7 +133,6 @@ def generate_nasa_13013_references(): ) - def generate_h265_video_references(): # This video was generated by running the following: # conda install -c conda-forge x265 diff --git a/test/test_transform_ops.py b/test/test_transform_ops.py index 036bd4c0e..238d44da1 100644 --- a/test/test_transform_ops.py +++ b/test/test_transform_ops.py @@ -40,7 +40,9 @@ def test_resize_torchvision(self, height_scaling_factor, width_scaling_factor): height = int(NASA_VIDEO.get_height() * height_scaling_factor) width = int(NASA_VIDEO.get_width() * width_scaling_factor) - decoder_resize = VideoDecoder(NASA_VIDEO.path, transforms=[v2.Resize(size=(height, width))]) + decoder_resize = VideoDecoder( + NASA_VIDEO.path, transforms=[v2.Resize(size=(height, width))] + ) decoder_full = VideoDecoder(NASA_VIDEO.path) for frame_index in [0, 10, 17, 100, 230, 389]: expected_shape = (NASA_VIDEO.get_num_color_channels(), height, width) @@ -60,16 +62,19 @@ def test_resize_ffmpeg(self): width = 240 expected_shape = (NASA_VIDEO.get_num_color_channels(), height, width) resize_filtergraph = f"scale={width}:{height}:flags=bilinear" - decoder_resize = VideoDecoder(NASA_VIDEO.path, transforms=[v2.Resize(size=(height, width))]) + decoder_resize = VideoDecoder( + NASA_VIDEO.path, transforms=[v2.Resize(size=(height, width))] + ) for frame_index in [17, 230, 389]: frame_resize = decoder_resize[frame_index] - frame_ref = NASA_VIDEO.get_frame_data_by_index(frame_index, filters=resize_filtergraph) + frame_ref = NASA_VIDEO.get_frame_data_by_index( + frame_index, filters=resize_filtergraph + ) assert frame_resize.shape == expected_shape assert frame_ref.shape == expected_shape assert_frames_equal(frame_resize, frame_ref) - def test_resize_fails(self): with pytest.raises( ValueError, @@ -84,6 +89,7 @@ def test_transform_fails(self): ): VideoDecoder(NASA_VIDEO.path, transforms=[v2.RandomHorizontalFlip(p=1.0)]) + class TestCoreVideoDecoderTransformOps: # We choose arbitrary values for width and height scaling to get better # test coverage. Some pairs upscale the image while others downscale it. From 98cf81bcc228d2b91813de9d580ebd25ba24d9bd Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 16:29:44 -0800 Subject: [PATCH 03/14] Implement decoder native transforms API --- src/torchcodec/decoders/_video_decoder.py | 61 ++++++++--- test/test_transform_ops.py | 122 +++++++++++----------- 2 files changed, 109 insertions(+), 74 deletions(-) diff --git a/src/torchcodec/decoders/_video_decoder.py b/src/torchcodec/decoders/_video_decoder.py index 5a29b8b19..59d7b38b8 100644 --- a/src/torchcodec/decoders/_video_decoder.py +++ b/src/torchcodec/decoders/_video_decoder.py @@ -8,7 +8,7 @@ import json import numbers from pathlib import Path -from typing import Any, List, Literal, Optional, Tuple, Union +from typing import Literal, Optional, Sequence, Tuple, Union import torch from torch import device as torch_device, Tensor @@ -19,6 +19,7 @@ create_decoder, ERROR_REPORTING_INSTRUCTIONS, ) +from torchcodec.transforms import DecoderNativeTransform, Resize class VideoDecoder: @@ -103,7 +104,7 @@ def __init__( dimension_order: Literal["NCHW", "NHWC"] = "NCHW", num_ffmpeg_threads: int = 1, device: Optional[Union[str, torch_device]] = "cpu", - transforms: List[Any] = [], # TRANSFORMS TODO: what is the user-facing type? + transforms: Optional[Sequence[DecoderNativeTransform]] = None, seek_mode: Literal["exact", "approximate"] = "exact", custom_frame_mappings: Optional[ Union[str, bytes, io.RawIOBase, io.BufferedReader] @@ -149,7 +150,7 @@ def __init__( device_variant = _get_cuda_backend() - transform_specs = make_transform_specs(transforms) + transform_specs = _make_transform_specs(transforms) core.add_video_stream( self._decoder, @@ -436,20 +437,56 @@ def _get_and_validate_stream_metadata( ) -def make_transform_specs(transforms: List[Any]) -> str: - from torchvision.transforms import v2 +# This function, _make_transform_specs, and the transforms argument to +# VideoDecoder actually accept a union of DecoderNativeTransform and +# TorchVision transforms. We don't put that in our type annotation because +# that would require importing torchvision at module scope which would mean we +# have a hard dependency on torchvision. +# TODO: better explanation of the above. +def _convert_to_decoder_native_transforms( + transforms: Sequence[DecoderNativeTransform], +) -> Sequence[DecoderNativeTransform]: + try: + from torchvision.transforms import v2 + + tv_available = True + except ImportError: + tv_available = False - transform_specs = [] + converted_transforms = [] for transform in transforms: - if isinstance(transform, v2.Resize): - if len(transform.size) != 2: + if not isinstance(transform, DecoderNativeTransform): + if not tv_available: + raise ValueError( + f"The supplied transform, {transform}, is not a TorchCodec " + " DecoderNativeTransform. TorchCodec also accept TorchVision " + "v2 transforms, but TorchVision is not installed." + ) + if isinstance(transform, v2.Resize): + if len(transform.size) != 2: + raise ValueError( + "TorchVision Resize transform must have a (height, width) " + f"pair for the size, got {transform.size}." + ) + converted_transforms.append(Resize(size=transform.size)) + else: raise ValueError( - f"Resize transform must have a (height, width) pair for the size, got {transform.size}." + f"Unsupported transform: {transform}. Transforms must be " + "either a TorchCodec DecoderNativeTransform or a TorchVision " + "v2 transform." ) - transform_specs.append(f"resize, {transform.size[0]}, {transform.size[1]}") else: - raise ValueError(f"Unsupported transform {transform}.") - return ";".join(transform_specs) + converted_transforms.append(transform) + + return converted_transforms + + +def _make_transform_specs(transforms: Optional[Sequence[DecoderNativeTransform]]) -> str: + if transforms is None: + return "" + + transforms = _convert_to_decoder_native_transforms(transforms) + return ";".join([t.make_params() for t in transforms]) def _read_custom_frame_mappings( diff --git a/test/test_transform_ops.py b/test/test_transform_ops.py index e45a19e53..2c5fc698a 100644 --- a/test/test_transform_ops.py +++ b/test/test_transform_ops.py @@ -37,6 +37,66 @@ class TestPublicVideoDecoderTransformOps: + @pytest.mark.parametrize( + "height_scaling_factor, width_scaling_factor", + ((1.5, 1.31), (0.5, 0.71), (0.7, 1.31), (1.5, 0.71), (1.0, 1.0), (2.0, 2.0)), + ) + @pytest.mark.parametrize("video", [NASA_VIDEO, TEST_SRC_2_720P]) + def test_resize_torchvision( + self, video, height_scaling_factor, width_scaling_factor + ): + height = int(video.get_height() * height_scaling_factor) + width = int(video.get_width() * width_scaling_factor) + + decoder_resize = VideoDecoder( + video.path, transforms=[v2.Resize(size=(height, width))] + ) + + decoder_full = VideoDecoder(video.path) + + num_frames = len(decoder_resize) + assert num_frames == len(decoder_full) + + for frame_index in [ + 0, + int(num_frames * 0.1), + int(num_frames * 0.2), + int(num_frames * 0.3), + int(num_frames * 0.4), + int(num_frames * 0.5), + int(num_frames * 0.75), + int(num_frames * 0.90), + num_frames - 1, + ]: + expected_shape = (video.get_num_color_channels(), height, width) + frame_resize = decoder_resize[frame_index] + frame_full = decoder_full[frame_index] + + frame_tv = v2.functional.resize(frame_full, size=(height, width)) + frame_tv_no_antialias = v2.functional.resize( + frame_full, size=(height, width), antialias=False + ) + + assert frame_resize.shape == expected_shape + assert frame_tv.shape == expected_shape + assert frame_tv_no_antialias.shape == expected_shape + + assert_tensor_close_on_at_least( + frame_resize, frame_tv, percentage=99.8, atol=1 + ) + torch.testing.assert_close(frame_resize, frame_tv, rtol=0, atol=6) + + if height_scaling_factor < 1 or width_scaling_factor < 1: + # Antialias only relevant when down-scaling! + with pytest.raises(AssertionError, match="Expected at least"): + assert_tensor_close_on_at_least( + frame_resize, frame_tv_no_antialias, percentage=99, atol=1 + ) + with pytest.raises(AssertionError, match="Tensor-likes are not close"): + torch.testing.assert_close( + frame_resize, frame_tv_no_antialias, rtol=0, atol=6 + ) + def test_resize_fails(self): with pytest.raises( ValueError, @@ -187,68 +247,6 @@ def test_transform_fails(self): ): add_video_stream(decoder, transform_specs="invalid, 1, 2") - @pytest.mark.parametrize( - "height_scaling_factor, width_scaling_factor", - ((1.5, 1.31), (0.5, 0.71), (0.7, 1.31), (1.5, 0.71), (1.0, 1.0), (2.0, 2.0)), - ) - @pytest.mark.parametrize("video", [NASA_VIDEO, TEST_SRC_2_720P]) - def test_resize_torchvision( - self, video, height_scaling_factor, width_scaling_factor - ): - num_frames = self.get_num_frames_core_ops(video) - - height = int(video.get_height() * height_scaling_factor) - width = int(video.get_width() * width_scaling_factor) - resize_spec = f"resize, {height}, {width}" - - decoder_resize = create_from_file(str(video.path)) - add_video_stream(decoder_resize, transform_specs=resize_spec) - - decoder_full = create_from_file(str(video.path)) - add_video_stream(decoder_full) - - for frame_index in [ - 0, - int(num_frames * 0.1), - int(num_frames * 0.2), - int(num_frames * 0.3), - int(num_frames * 0.4), - int(num_frames * 0.5), - int(num_frames * 0.75), - int(num_frames * 0.90), - num_frames - 1, - ]: - expected_shape = (video.get_num_color_channels(), height, width) - frame_resize, *_ = get_frame_at_index( - decoder_resize, frame_index=frame_index - ) - - frame_full, *_ = get_frame_at_index(decoder_full, frame_index=frame_index) - frame_tv = v2.functional.resize(frame_full, size=(height, width)) - frame_tv_no_antialias = v2.functional.resize( - frame_full, size=(height, width), antialias=False - ) - - assert frame_resize.shape == expected_shape - assert frame_tv.shape == expected_shape - assert frame_tv_no_antialias.shape == expected_shape - - assert_tensor_close_on_at_least( - frame_resize, frame_tv, percentage=99.8, atol=1 - ) - torch.testing.assert_close(frame_resize, frame_tv, rtol=0, atol=6) - - if height_scaling_factor < 1 or width_scaling_factor < 1: - # Antialias only relevant when down-scaling! - with pytest.raises(AssertionError, match="Expected at least"): - assert_tensor_close_on_at_least( - frame_resize, frame_tv_no_antialias, percentage=99, atol=1 - ) - with pytest.raises(AssertionError, match="Tensor-likes are not close"): - torch.testing.assert_close( - frame_resize, frame_tv_no_antialias, rtol=0, atol=6 - ) - def test_resize_ffmpeg(self): height = 135 width = 240 From 65c4ad762c3afc7992113225fbe81d66330d795a Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 16:32:54 -0800 Subject: [PATCH 04/14] Correct merge --- test/generate_reference_resources.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/generate_reference_resources.py b/test/generate_reference_resources.py index f2890bd55..f95ff3642 100644 --- a/test/generate_reference_resources.py +++ b/test/generate_reference_resources.py @@ -127,14 +127,6 @@ def generate_nasa_13013_references_crop(): NASA_VIDEO, frame_index=frame, stream_index=3, filters=crop_filter ) - frames = [17, 230, 389] - # Note that the resize algorithm passed to flags is exposed to users, - # but bilinear is the default we use. - resize_filter = "scale=240:135:flags=bilinear" - for frame in frames: - generate_frame_by_index( - NASA_VIDEO, frame_index=frame, stream_index=3, filters=resize_filter - ) def generate_nasa_13013_references_resize(): From f300c70a5240f6a5c8b583de8c82e869fa11b34a Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 16:35:52 -0800 Subject: [PATCH 05/14] Actually add new file --- .../transforms/_decoder_native_transforms.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/torchcodec/transforms/_decoder_native_transforms.py diff --git a/src/torchcodec/transforms/_decoder_native_transforms.py b/src/torchcodec/transforms/_decoder_native_transforms.py new file mode 100644 index 000000000..8c3de1c4c --- /dev/null +++ b/src/torchcodec/transforms/_decoder_native_transforms.py @@ -0,0 +1,36 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +from dataclasses import dataclass +from abc import ABC, abstractmethod +from typing import Sequence + + +@dataclass +class DecoderNativeTransform(ABC): + """TODO: docstring""" + @abstractmethod + def make_params(self) -> str: + pass + + +@dataclass +class Resize(DecoderNativeTransform): + """ + TODO. One benefit of having parallel definitions is that it gives us a place + to put documentation about what behavior we do and do not support. For + example, we don't yet have fields for `interpolation` and `antialias` + because we don't allow users to control those yet in decoder-native + transforms. + """ + + # Also note that this type is more restrictive than what TorchVision + # accepts, but it accurately reflects current decoder-native transform + # limitations. + size: Sequence[int] + + def make_params(self) -> str: + return f"resize, {self.size[0]}, {self.size[1]}" From 2c3b7f01f0f94963b3b482fd50266a33dff7d768 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 16:37:08 -0800 Subject: [PATCH 06/14] Lint --- src/torchcodec/decoders/_video_decoder.py | 4 +++- src/torchcodec/transforms/_decoder_native_transforms.py | 3 ++- test/generate_reference_resources.py | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/torchcodec/decoders/_video_decoder.py b/src/torchcodec/decoders/_video_decoder.py index 59d7b38b8..5695679a0 100644 --- a/src/torchcodec/decoders/_video_decoder.py +++ b/src/torchcodec/decoders/_video_decoder.py @@ -481,7 +481,9 @@ def _convert_to_decoder_native_transforms( return converted_transforms -def _make_transform_specs(transforms: Optional[Sequence[DecoderNativeTransform]]) -> str: +def _make_transform_specs( + transforms: Optional[Sequence[DecoderNativeTransform]], +) -> str: if transforms is None: return "" diff --git a/src/torchcodec/transforms/_decoder_native_transforms.py b/src/torchcodec/transforms/_decoder_native_transforms.py index 8c3de1c4c..4af64969e 100644 --- a/src/torchcodec/transforms/_decoder_native_transforms.py +++ b/src/torchcodec/transforms/_decoder_native_transforms.py @@ -4,14 +4,15 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. -from dataclasses import dataclass from abc import ABC, abstractmethod +from dataclasses import dataclass from typing import Sequence @dataclass class DecoderNativeTransform(ABC): """TODO: docstring""" + @abstractmethod def make_params(self) -> str: pass diff --git a/test/generate_reference_resources.py b/test/generate_reference_resources.py index f95ff3642..3821c9299 100644 --- a/test/generate_reference_resources.py +++ b/test/generate_reference_resources.py @@ -128,7 +128,6 @@ def generate_nasa_13013_references_crop(): ) - def generate_nasa_13013_references_resize(): frames = [17, 230, 389] # Note that the resize algorithm passed to flags is exposed to users, From 80e84b56a6f01116dfc06716835532ac563b42cd Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 16:39:25 -0800 Subject: [PATCH 07/14] Better assert --- src/torchcodec/transforms/_decoder_native_transforms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/torchcodec/transforms/_decoder_native_transforms.py b/src/torchcodec/transforms/_decoder_native_transforms.py index 4af64969e..952ea77bb 100644 --- a/src/torchcodec/transforms/_decoder_native_transforms.py +++ b/src/torchcodec/transforms/_decoder_native_transforms.py @@ -34,4 +34,5 @@ class Resize(DecoderNativeTransform): size: Sequence[int] def make_params(self) -> str: + assert len(self.size) == 2 return f"resize, {self.size[0]}, {self.size[1]}" From 5ac60d806baa1b6b21870b7d8fdc7c8095923c07 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 16:40:44 -0800 Subject: [PATCH 08/14] Better comment --- src/torchcodec/transforms/_decoder_native_transforms.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/torchcodec/transforms/_decoder_native_transforms.py b/src/torchcodec/transforms/_decoder_native_transforms.py index 952ea77bb..b0d7918f5 100644 --- a/src/torchcodec/transforms/_decoder_native_transforms.py +++ b/src/torchcodec/transforms/_decoder_native_transforms.py @@ -30,7 +30,8 @@ class Resize(DecoderNativeTransform): # Also note that this type is more restrictive than what TorchVision # accepts, but it accurately reflects current decoder-native transform - # limitations. + # limitations. We can reflect that not just in our docs, but also type + # annotations. size: Sequence[int] def make_params(self) -> str: From 531b40f404051666c3cc88539bb755c2f0f0614e Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 19:38:16 -0800 Subject: [PATCH 09/14] Top level transforms import --- src/torchcodec/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/torchcodec/__init__.py b/src/torchcodec/__init__.py index c0f4c2b6d..9ea601fde 100644 --- a/src/torchcodec/__init__.py +++ b/src/torchcodec/__init__.py @@ -7,7 +7,7 @@ # Note: usort wants to put Frame and FrameBatch after decoders and samplers, # but that results in circular import. from ._frame import AudioSamples, Frame, FrameBatch # usort:skip # noqa -from . import decoders, encoders, samplers # noqa +from . import decoders, encoders, samplers, transforms # noqa try: # Note that version.py is generated during install. From cc333ac5d43c637a819444bf36254a99256777c1 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 19:44:26 -0800 Subject: [PATCH 10/14] Add the init file. Sigh. --- src/torchcodec/transforms/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/torchcodec/transforms/__init__.py diff --git a/src/torchcodec/transforms/__init__.py b/src/torchcodec/transforms/__init__.py new file mode 100644 index 000000000..3d4462fd1 --- /dev/null +++ b/src/torchcodec/transforms/__init__.py @@ -0,0 +1,7 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +from ._decoder_native_transforms import DecoderNativeTransform, Resize # noqa From 238a8ff92a986b2606481ff8e3434e8b61a51a18 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 19:52:20 -0800 Subject: [PATCH 11/14] Linter now needs torchvision in the environment --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index c156a833c..57a4916a4 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -62,7 +62,7 @@ jobs: run: python -m pip install --upgrade pip - name: Install dependencies and FFmpeg run: | - python -m pip install --pre torch --index-url https://download.pytorch.org/whl/nightly/cpu + python -m pip install --pre torch torchvision --index-url https://download.pytorch.org/whl/nightly/cpu conda install "ffmpeg=7.0.1" pkg-config pybind11 -c conda-forge ffmpeg -version - name: Build and install torchcodec From 55d362c5828f4c997884aaa6317625edb1e72567 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Thu, 6 Nov 2025 20:13:34 -0800 Subject: [PATCH 12/14] Avoid missing import errors --- mypy.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/mypy.ini b/mypy.ini index bd0ee6ac8..f018ba4f8 100644 --- a/mypy.ini +++ b/mypy.ini @@ -4,3 +4,4 @@ files = src/torchcodec show_error_codes = True pretty = True allow_redefinition = True +follow_untyped_imports = True From 0d2492e9dd89c93b9ffe6619e3af0534d5f3617a Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Fri, 7 Nov 2025 18:40:47 -0800 Subject: [PATCH 13/14] Better names, better docs --- src/torchcodec/decoders/_video_decoder.py | 57 +++++++++++++----- src/torchcodec/transforms/__init__.py | 2 +- .../transforms/_decoder_native_transforms.py | 39 ------------- .../transforms/_decoder_transforms.py | 58 +++++++++++++++++++ 4 files changed, 101 insertions(+), 55 deletions(-) delete mode 100644 src/torchcodec/transforms/_decoder_native_transforms.py create mode 100644 src/torchcodec/transforms/_decoder_transforms.py diff --git a/src/torchcodec/decoders/_video_decoder.py b/src/torchcodec/decoders/_video_decoder.py index 5695679a0..68b1fe3c2 100644 --- a/src/torchcodec/decoders/_video_decoder.py +++ b/src/torchcodec/decoders/_video_decoder.py @@ -8,7 +8,7 @@ import json import numbers from pathlib import Path -from typing import Literal, Optional, Sequence, Tuple, Union +from typing import List, Literal, Optional, Sequence, Tuple, Union import torch from torch import device as torch_device, Tensor @@ -19,7 +19,7 @@ create_decoder, ERROR_REPORTING_INSTRUCTIONS, ) -from torchcodec.transforms import DecoderNativeTransform, Resize +from torchcodec.transforms import DecoderTransform, Resize class VideoDecoder: @@ -67,6 +67,10 @@ class VideoDecoder: probably is. Default: "exact". Read more about this parameter in: :ref:`sphx_glr_generated_examples_decoding_approximate_mode.py` + transforms (sequence of transform objects, optional): Sequence of transforms to be + applied to the decoded frames by the decoder itself, in order. Accepts both + torchcodec.transforms.DecoderTransform and torchvision.transforms.v2.Transform + objects. All transforms are applied in the ouput pixel format and colorspace. custom_frame_mappings (str, bytes, or file-like object, optional): Mapping of frames to their metadata, typically generated via ffprobe. This enables accurate frame seeking without requiring a full video scan. @@ -104,8 +108,8 @@ def __init__( dimension_order: Literal["NCHW", "NHWC"] = "NCHW", num_ffmpeg_threads: int = 1, device: Optional[Union[str, torch_device]] = "cpu", - transforms: Optional[Sequence[DecoderNativeTransform]] = None, seek_mode: Literal["exact", "approximate"] = "exact", + transforms: Optional[Sequence[DecoderTransform]] = None, custom_frame_mappings: Optional[ Union[str, bytes, io.RawIOBase, io.BufferedReader] ] = None, @@ -437,15 +441,23 @@ def _get_and_validate_stream_metadata( ) -# This function, _make_transform_specs, and the transforms argument to -# VideoDecoder actually accept a union of DecoderNativeTransform and -# TorchVision transforms. We don't put that in our type annotation because -# that would require importing torchvision at module scope which would mean we -# have a hard dependency on torchvision. -# TODO: better explanation of the above. def _convert_to_decoder_native_transforms( - transforms: Sequence[DecoderNativeTransform], -) -> Sequence[DecoderNativeTransform]: + transforms: Sequence[DecoderTransform], +) -> List[DecoderTransform]: + """Convert a sequence of transforms that may contain TorchVision transform + objects into a list of only TorchCodec transform objects. + + Args: + transforms: Squence of transform objects. The objects can be one of two + types: + 1. torchcodec.transforms.DecoderTransform + 2. torchvision.transforms.v2.Transform + Our type annotation only mentions the first type so that we don't + have a hard dependency on TorchVision. + + Returns: + List of DecoderTransform objects. + """ try: from torchvision.transforms import v2 @@ -455,11 +467,11 @@ def _convert_to_decoder_native_transforms( converted_transforms = [] for transform in transforms: - if not isinstance(transform, DecoderNativeTransform): + if not isinstance(transform, DecoderTransform): if not tv_available: raise ValueError( f"The supplied transform, {transform}, is not a TorchCodec " - " DecoderNativeTransform. TorchCodec also accept TorchVision " + " DecoderTransform. TorchCodec also accept TorchVision " "v2 transforms, but TorchVision is not installed." ) if isinstance(transform, v2.Resize): @@ -472,7 +484,7 @@ def _convert_to_decoder_native_transforms( else: raise ValueError( f"Unsupported transform: {transform}. Transforms must be " - "either a TorchCodec DecoderNativeTransform or a TorchVision " + "either a TorchCodec DecoderTransform or a TorchVision " "v2 transform." ) else: @@ -482,8 +494,23 @@ def _convert_to_decoder_native_transforms( def _make_transform_specs( - transforms: Optional[Sequence[DecoderNativeTransform]], + transforms: Optional[Sequence[DecoderTransform]], ) -> str: + """Given a sequence of transforms, turn those into the specification string + the core API expects. + + Args: + transforms: Optional sequence of transform objects. The objects can be + one of two types: + 1. torchcodec.transforms.DecoderTransform + 2. torchvision.transforms.v2.Transform + Our type annotation only mentions the first type so that we don't + have a hard dependency on TorchVision. + + Returns: + String of transforms in the format the core API expects: transform + specifications separate by semicolons. + """ if transforms is None: return "" diff --git a/src/torchcodec/transforms/__init__.py b/src/torchcodec/transforms/__init__.py index 3d4462fd1..9f4a92f81 100644 --- a/src/torchcodec/transforms/__init__.py +++ b/src/torchcodec/transforms/__init__.py @@ -4,4 +4,4 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. -from ._decoder_native_transforms import DecoderNativeTransform, Resize # noqa +from ._decoder_transforms import DecoderTransform, Resize # noqa diff --git a/src/torchcodec/transforms/_decoder_native_transforms.py b/src/torchcodec/transforms/_decoder_native_transforms.py deleted file mode 100644 index b0d7918f5..000000000 --- a/src/torchcodec/transforms/_decoder_native_transforms.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. -# -# This source code is licensed under the BSD-style license found in the -# LICENSE file in the root directory of this source tree. - -from abc import ABC, abstractmethod -from dataclasses import dataclass -from typing import Sequence - - -@dataclass -class DecoderNativeTransform(ABC): - """TODO: docstring""" - - @abstractmethod - def make_params(self) -> str: - pass - - -@dataclass -class Resize(DecoderNativeTransform): - """ - TODO. One benefit of having parallel definitions is that it gives us a place - to put documentation about what behavior we do and do not support. For - example, we don't yet have fields for `interpolation` and `antialias` - because we don't allow users to control those yet in decoder-native - transforms. - """ - - # Also note that this type is more restrictive than what TorchVision - # accepts, but it accurately reflects current decoder-native transform - # limitations. We can reflect that not just in our docs, but also type - # annotations. - size: Sequence[int] - - def make_params(self) -> str: - assert len(self.size) == 2 - return f"resize, {self.size[0]}, {self.size[1]}" diff --git a/src/torchcodec/transforms/_decoder_transforms.py b/src/torchcodec/transforms/_decoder_transforms.py new file mode 100644 index 000000000..ca889abd1 --- /dev/null +++ b/src/torchcodec/transforms/_decoder_transforms.py @@ -0,0 +1,58 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import Sequence + + +@dataclass +class DecoderTransform(ABC): + """Base class for all decoder transforms. + + A DecoderTransform is a transform that is applied by the decoder before + returning the decoded frame. The implementation does not live in TorchCodec + itself, but in the underyling decoder. Applying DecoderTransforms to frames + should be both faster and more memory efficient than receiving normally + decoded frames and applying the same kind of transform. + + Most DecoderTransforms have a complementary transform in TorchVision, + specificially in torchvision.transforms.v2. For such transforms, we ensure + that: + + 1. Default behaviors are the same. + 2. The parameters for the DecoderTransform are a subset of the + TorchVision transform. + 3. Parameters with the same name control the same behavior and accept a + subset of the same types. + 4. The difference between the frames returned by a DecoderTransform and + the complementary TorchVision transform are small. + + All DecoderTranforms are applied in the output pixel format and colorspace. + """ + + @abstractmethod + def make_params(self) -> str: + pass + + +@dataclass +class Resize(DecoderTransform): + """Resize the decoded frame to a given size. + + Complementary TorchVision transform: torchvision.transforms.v2.Resize. + Interpolation is always bilinear. Anti-aliasing is always on. + + Args: + size: (sequence of int): Desired output size. Must be a sequence of + the form (height, width). + """ + + size: Sequence[int] + + def make_params(self) -> str: + assert len(self.size) == 2 + return f"resize, {self.size[0]}, {self.size[1]}" From a2da767bf56edfb6a10952ee37defe13979a35e4 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Sun, 9 Nov 2025 18:10:40 -0800 Subject: [PATCH 14/14] More testing, docstring editing --- src/torchcodec/decoders/_video_decoder.py | 2 +- test/test_transform_ops.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/torchcodec/decoders/_video_decoder.py b/src/torchcodec/decoders/_video_decoder.py index 68b1fe3c2..af8b9e99d 100644 --- a/src/torchcodec/decoders/_video_decoder.py +++ b/src/torchcodec/decoders/_video_decoder.py @@ -69,7 +69,7 @@ class VideoDecoder: :ref:`sphx_glr_generated_examples_decoding_approximate_mode.py` transforms (sequence of transform objects, optional): Sequence of transforms to be applied to the decoded frames by the decoder itself, in order. Accepts both - torchcodec.transforms.DecoderTransform and torchvision.transforms.v2.Transform + ``torchcodec.transforms.DecoderTransform`` and ``torchvision.transforms.v2.Transform`` objects. All transforms are applied in the ouput pixel format and colorspace. custom_frame_mappings (str, bytes, or file-like object, optional): Mapping of frames to their metadata, typically generated via ffprobe. diff --git a/test/test_transform_ops.py b/test/test_transform_ops.py index 2c5fc698a..edc3cfe15 100644 --- a/test/test_transform_ops.py +++ b/test/test_transform_ops.py @@ -13,6 +13,7 @@ import pytest import torch +import torchcodec from torchcodec._core import ( _add_video_stream, @@ -48,7 +49,12 @@ def test_resize_torchvision( height = int(video.get_height() * height_scaling_factor) width = int(video.get_width() * width_scaling_factor) + # We're using both the TorchCodec object and the TorchVision object to + # ensure that they specify exactly the same thing. decoder_resize = VideoDecoder( + video.path, transforms=[torchcodec.transforms.Resize(size=(height, width))] + ) + decoder_resize_tv = VideoDecoder( video.path, transforms=[v2.Resize(size=(height, width))] ) @@ -68,8 +74,10 @@ def test_resize_torchvision( int(num_frames * 0.90), num_frames - 1, ]: - expected_shape = (video.get_num_color_channels(), height, width) + frame_resize_tv = decoder_resize_tv[frame_index] frame_resize = decoder_resize[frame_index] + assert_frames_equal(frame_resize_tv, frame_resize) + frame_full = decoder_full[frame_index] frame_tv = v2.functional.resize(frame_full, size=(height, width)) @@ -77,6 +85,7 @@ def test_resize_torchvision( frame_full, size=(height, width), antialias=False ) + expected_shape = (video.get_num_color_channels(), height, width) assert frame_resize.shape == expected_shape assert frame_tv.shape == expected_shape assert frame_tv_no_antialias.shape == expected_shape