From b1d49961ef19c5507772aaf6beb88be5d89010d8 Mon Sep 17 00:00:00 2001 From: Ahmad Sharif Date: Tue, 13 Aug 2024 10:07:24 -0700 Subject: [PATCH] [torchcodec] Return subsequent frame if FFMPEG seeks past end of the frame (#178) Summary: Pull Request resolved: https://github.com/pytorch/torchcodec/pull/178 The way get_frame_displayed_at works is as follows: We call avformat_seek_file with: `min_ts=-inf ts=timestamp max_ts=timestamp` https://ffmpeg.org/doxygen/7.0/group__lavf__decoding.html#ga3b40fc8d2fda6992ae6ea2567d71ba30 This should in theory never seek past our timestamp. However for some videos ffmpeg does seek past our timestamp. And that causes us to never return a valid frame in that case. The fix is to warn the user and return the first frame after the timestamp if this ever happens. Reviewed By: NicolasHug Differential Revision: D61139386 --- src/torchcodec/decoders/_core/VideoDecoder.cpp | 10 ++++++++++ test/decoders/test_simple_video_decoder.py | 11 ++++++++++- test/generate_reference_resources.sh | 13 ++++++++++++- test/resources/h265_video.mp4 | Bin 0 -> 17704 bytes test/resources/h265_video.mp4.frame000006.pt | Bin 0 -> 50491 bytes test/utils.py | 14 ++++++++++++++ 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 test/resources/h265_video.mp4 create mode 100644 test/resources/h265_video.mp4.frame000006.pt diff --git a/src/torchcodec/decoders/_core/VideoDecoder.cpp b/src/torchcodec/decoders/_core/VideoDecoder.cpp index 4c9d00122..4e7ae4406 100644 --- a/src/torchcodec/decoders/_core/VideoDecoder.cpp +++ b/src/torchcodec/decoders/_core/VideoDecoder.cpp @@ -940,6 +940,16 @@ VideoDecoder::DecodedOutput VideoDecoder::getFrameDisplayedAtTimestampNoDemux( double frameStartTime = ptsToSeconds(frame->pts, stream.timeBase); double frameEndTime = ptsToSeconds(frame->pts + getDuration(frame), stream.timeBase); + if (frameStartTime > seconds) { + // FFMPEG seeked past the frame we are looking for even though we + // set max_ts to be our needed timestamp in avformat_seek_file() + // in maybeSeekToBeforeDesiredPts(). + // This could be a bug in FFMPEG: https://trac.ffmpeg.org/ticket/11137 + // In this case we return the very next frame instead of throwing an + // exception. + // TODO: Maybe log to stderr for Debug builds? + return true; + } return seconds >= frameStartTime && seconds < frameEndTime; }); } diff --git a/test/decoders/test_simple_video_decoder.py b/test/decoders/test_simple_video_decoder.py index e7d4d8915..ff87a63d7 100644 --- a/test/decoders/test_simple_video_decoder.py +++ b/test/decoders/test_simple_video_decoder.py @@ -9,7 +9,7 @@ from torchcodec.decoders import _core, SimpleVideoDecoder -from ..utils import assert_tensor_close, assert_tensor_equal, NASA_VIDEO +from ..utils import assert_tensor_close, assert_tensor_equal, H265_VIDEO, NASA_VIDEO class TestSimpleDecoder: @@ -320,6 +320,15 @@ def test_get_frame_displayed_at(self): assert isinstance(decoder.get_frame_displayed_at(6.02).pts_seconds, float) assert isinstance(decoder.get_frame_displayed_at(6.02).duration_seconds, float) + def test_get_frame_displayed_at_h265(self): + decoder = SimpleVideoDecoder(H265_VIDEO.path) + # Note that for H265, FFMPEG's seeking is not precise. Even though we ask to + # seek with a max_ts=0.5, FFMPEG will seek beyond that point. + # TODO: Revert use frame5 in the test below once it's fixed upstream: + # https://trac.ffmpeg.org/ticket/11137 + ref_frame6 = H265_VIDEO.get_frame_by_name("frame000006") + assert_tensor_equal(ref_frame6, decoder.get_frame_displayed_at(0.5).data) + def test_get_frame_displayed_at_fails(self): decoder = SimpleVideoDecoder(NASA_VIDEO.path) diff --git a/test/generate_reference_resources.sh b/test/generate_reference_resources.sh index 7f9985092..1fdb84deb 100755 --- a/test/generate_reference_resources.sh +++ b/test/generate_reference_resources.sh @@ -42,8 +42,19 @@ ffmpeg -y -i "$VIDEO_PATH" -b:a 192K -vn "$VIDEO_PATH.audio.mp3" # TODO: Add frames decoded by Nvidia's NVDEC. +# This video was generated by running the following: +# conda install -c conda-forge x265 +# ./configure --enable-nonfree --enable-gpl --prefix=$(readlink -f ../bin) --enable-libx265 --enable-rpath --extra-ldflags=-Wl,-rpath=$CONDA_PREFIX/lib --enable-filter=drawtext --enable-libfontconfig --enable-libfreetype --enable-libharfbuzz +# ffmpeg -f lavfi -i color=size=128x128:duration=1:rate=10:color=blue -vf "drawtext=fontsize=30:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:text='Frame %{frame_num}'" -vcodec libx265 -pix_fmt yuv420p -g 2 -crf 10 h265_video.mp4 -y +VIDEO_PATH=$RESOURCES_DIR/h265_video.mp4 +FRAMES=(6) +for frame in "${FRAMES[@]}"; do + frame_name=$(printf "%06d" "$frame") + ffmpeg -y -i "$VIDEO_PATH" -vf select="eq(n\,$frame)" -vsync vfr -q:v 2 "$VIDEO_PATH.frame$frame_name.bmp" +done + for bmp in "$RESOURCES_DIR"/*.bmp do - python3 convert_image_to_tensor.py "$bmp" + python3 "$TORCHCODEC_PATH/test/convert_image_to_tensor.py" "$bmp" rm -f "$bmp" done diff --git a/test/resources/h265_video.mp4 b/test/resources/h265_video.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..33b8457f392e9c4636e12b9b634b3b868ad65f9b GIT binary patch literal 17704 zcmeIaby!s2*El+Kw}gl=lmgNq4N6IeARRI=0}L<>Ftn6_gn*PH2oloWjiiLMv>@Gr z5|UECGwAp8e%|-q`#krL``o|YjpyvW*4}IFwO5_RaRv|w#9-~}S%My&15-OH#BjjGicwnQ;GJ~ zsU?OYc3OIfPDOxxDr(7bdtC--rz=Xj8dllvq*U zeNc?!k}ry3^JSQbsUJP1k<};oPU)0+$@KAG-yWMDW2$fB+%S94xn)1q;Do`SS`dLh z665dp*7MzHgiam^qv02C^qWP<(o0s1x*}FO_TrGHr>vxuU~#4e)wuBSjX5()dh-{D z!cHq(iukpZx~rhb#>FTZmqOB|fO!~nCd$S;He%GfK(z=foa7y@SrD&D9mJDsEiczKI!;Jj$Vvgp?Z&x z?i}rMkSUKv9?lbES2J_V<#v9GeV)e@&NnaZY2k+>6q`+P5Kgbo%zLxu)%ugV1IPxm zTpo7qXUN;%6mF&@n)h0H-*$6>x zJE^N|Zd|N7`E^KkP*E@S?y6@@SPJH?<9=Rxnt8MBNVwF93UiuMP)CJn{cS??M(f$ZrbuHf3%&NO*7Eu?E2Zh?_2T3{M$;hsg6N# z-_6(l2li8;il#0Dt{!SkAlAbkdQYr%c!R&ErXN#T^gE)S?#6dWYPHgFn&v@X4HZ}Z zj|xOCQbVsK$VG$*6UqehSY$h?q-?0AFN5Qy!V0)laqM_mY;3pNZ*vASWVKgZ<#2UI zVt;)9X=^X1VJY0&G2kI3$@<-6nd%e?sN*yvkKLECfaD)NJ}tC|+d4g%SjNPhn_Z3D zl0pi>C#^Flt%08M59JF|O`g^<_RZ%hiH(ASF$@-{5 z5b`jL`t$0;OY8e)I=}6Ai9#p7wBf)-X(}1HNsWOg($f$g>mezY#vs6EHNBJw_YTPrz*?PJgW7Wed(GUHdF zuP@2Fz*zj{V`7hEX5aaB37hq>mE1eNG@p{IrXchdmh>AQ)^KTU&-@sQ(Ux}C{1bIK zS+zQ)v&_;OS7^08Ez>u|#L9&*56(l1rChOIIj@hh&NJIBd(WXvJuHBCg%EEA)LUoZ z#mOXkJdP$U_cAtcn{vwed@jy2ynl;TAKD>uQ>4>3&&$^>B3hj(b{S_~$OVVj7>4*(*6~u7|q%u$kB@snz>$#l?F)!vitW z#mS|rXzi5jHhPjvP`AmsqnyqXMzlesD$%cW?`>tqCyKOS?`OYzzsAAjz#-&ee3nTq zetDxn>ama*q#(j9|8S^m*=APoCgJPzLy}+Qqglr}B5q$Y4syilWI1g11x~OxVInJL z>HBS@g>(9r-^S)2bmKNx4KItA_N?8{GG@>3C*Tb;K%mrCRtJ7ou`V_{Quq!8+BrCe z;e=*+YumGvavt4`Yj{XKaZdl0dobxjOQ^0+Oq!`Mvd0l25=BwmjU=U+lXD?pTIdyB z|J1tn=EKqF<_pGRtG5{;KA?Nz8R9CY>QGCs1ER~L>`k}bo`VU503p3TrJ`|TMxFf& zF6Htc@jL21F6)c6c3j36!LgtAZDm(<7sT9HDLu#daWdHme<57A%7{4UWQYBRY(9WV zZTprMcMXGm%CqkRgxo1*AI4G^KL*Nxx#M&rNj$;M@h2m~fG z{rNtW7Q#PH(4&$B54&tDw#k(N!;ilrK@Ez&xyJC zMP55@1O}_P z%OvQUHvC^+ZdMJ^3z8Dlr0qU9ZNsf&j0_PQ<#Y=9VND*UY@OCX65lD$_&+1pV6Tj7u;M}j=nlr2ocse1NYVvr(a4+rj!`|eh_|4f*3Iqu^jSi1d z&B0e#21u6Nu;{D@m6CJbNzcx$7AfpgNgX`OlV5C0 z?k|);!U?`V?r?9g-oNFq=b}{```#mSlvwk5%nSiIrGQD5iIteq04jb{Yb;Tb;FD4z zHntM}=MPgAmMyGawhPn|MsL1#tm``pitVkjx7Sr?Bg3a9YVcXp5t!HTX;vo}Jio zvC}qcOP#y>pc|fUa%TJBYdIFCa$r)|tM6ZAzW)wa3EEz1PRr{@hWTHH1&IZVBPNDX+98X;{Ag}NH7su5IC*q*sc%DUh!SC9IT3dlo$?l1AQ2gzk;-e}Ovb9j< zp05B+!-qT6H(FbUTJ3*+q@Q{aMrp)bD;T^02!rnP2a)(Q--Z zYW1A^e55lYHZC$XCy&aXa%_xyDGyp+vODi3fxGEpyn_e-i zCfeL`5z3gv+FAmt+I=pJBK*TP!tVnPwjCl=7pq6!SIhWUSE;8-#gOM*RJLOh9||v< z>7JdwpL?pb7lZP@+6*;3|K3QzTDu~-k=ulL@|a{Ucq!=ZGG~(*&zQDj+na3i$;n=l zOM7g*DRoVY)9M#g>CBD}&5@xlmd9oBU3^TfzR?;6@5xboF#YkgR8I%@E~S!4ubQrJ z45-$-IP_Gg?FACRH92j?Zz-Du4|v?UpIOJc!Tr_5cR zk5=W#)VxvBtoahF%`vG(nCyLw_63e=b*8A#R*!XTvZxjYG5m)4Ygx%5qpu)VoTK4Rb`gZ%5uOHK@mjqw~a@B3xyrY16s`}moV24Uo& zM@AW?$WN08e)0ZGFIa!nogKwl?G#&jbF<%Di`#$#FbckZ9Sjufj49h6$?X-t9g_{UYNpp3H!77Q3{e17u ziDNfoNYpQiaw|iy|DD_6J=uM>kMlMN83s-g32P|Yk0Q2G_YB2IA7z_~h`yW5+2c7< zDfVFo&k^(AqwcGU%w8o?8W`d5p{2gmc_zKcq zMklO(SxyE&E9<-chUKd z!F*1$k_gX%dm&N2Uma`5I$7OtT0zlka8$TmiIk}|y~^pK^PPlc#wbF94A2ddHHgz^ z4eLjHOc;mUW12}x){n{uu0FOYTBwqJ$og$4NySus260ekDz8#?7%#j0AXo_z{DP^c z=pkl(FMj!blt5>J7pN!9G)!q^*iv-vU4XW1gW^(-D)S);rMeJJtftvQ7rp!pYTExw z=87OHr}%`;WlgK?of~3i%C&R_-XEn9NwzO4`BN5`@2ESz*v2e=z2zf6-(0~JWn0vJ z1HaM`DN+m4Qu&<+;z8PjB!jmYLj|%gQ^k?P1l&Wp9d)`vD=Xugg2eQNibEwaLB1B6leI#b6=UH63$enJQJjL2| zF@Nmjhw}a&>+LbcYb?d(3d4U|osPf?it^Z06ZlaJJk1HlcGJl#B94c!Rl4GxU(<{- zj<7dWl2hUa2bXi4e^qz<4kG;Oru*b)CBK|SUr1|V?Iam;NK%P@CnRM#Q&fIMlU~C6 z5+pOxU@ClJiAgHw?f!fHi|+R$9uC4W~zMt=Tfzg{RvwrTQON#fw z$tm!=?D+B|%ayiDK{qSQTcXrQyW=56nV@KdyIg0dp03ECwdAJL50O~K;qa0sk~@~T z#)CfX-I9rJ(&m(JA|7K@f#*1PEI%&6pOIsRb^44Kh-gk^$+Ol|=9|k-Fr(4fxh3=hMcxHR)63u)m5)!S!&?JJ@WVSZ`l-3UFH+#tHCVKQFXqby|;e;a7d+y zLUZB>gu`3uHbs@(g4GsuhyJDg&#m@~JF@$=B?MG@r%ziE?cvR7*38 z1v?XsiQ=NgcCF1RSZ(#WIK5Y*9)+3u&9ZPrtF{E7+t8Xq81pkMjwrR2*#+>z@y-p zC4G~IWj^#Y=dpv8&vx~9=$8Kxm!AQJwc}#``5?`epEPk52xLK>s&HG*A2|xjr%~3b zGTGk8{Bgw*Hb^UNRk_-ia+0WogNLuiVBzYaRA%~O1T{}@G?}R4|F9(;n{u{)8}jDB zOy8nuQReS`m-Lh;LImsDM)AKJ z*SJrc9w;C&Rd2sG*EQ>6;rND!yIU00^QLWvmP>T1^dTrJn`HTGrx($%SL5NuQ>JM- z3;2t)ceZun9jPYf=jtC)$tJ$2rk5yPU5=0>JbDZbn%cD$Rvd}g!xMUxtC>`+M5D9% z{?j5hQUL2^O&xS6)YFL~G2L%oP0iUz$i;uY<>SZ49X#qHloA=Ir;bRO%n(9ED-|N%$Sp zx+eq(zPuNtc2e7g%7j7Y3sf_gjwPlxrmqSw4&j^FawL|fx@>||^|o_;RSFl&*k@4{ zglf5}7aZ=aA#;ZJW-TK@E+p)Zyo*~MF>L3y@o{>f(s@V7Sob6Vm#K-H$@qu%xtgzc~--{xVmwb9!Sis00H;l$x-10@eAUM!1s&GH4RJ`AAhBhT-sL%+>@A#rteBQPa; zbC>U`5&24$zsHoK#lDwBjm&gOtJ>v7;yiKLk^j}1q}uWT|6S|N**ZGz*LP(7jy6xT z!!hhJ86UTi%`Pq#+08qBSydKl{>mi+JuTv!n?%0E!rDIMY<#-go74kfLJ`g=UUqv%^ZsnctEp@|=_-;m}zE)+k+%eO*8(i$TdHpb=Y zW(lU}U%Cq|ebC1l?pmGq>|*qd`IwaCJuwqKQ`ehAzg2_c{#Gg`$#f;@U@o{EPJ+}Ue z>1SCT;pZd@DSz|%Z;pPr!ST6*Kk}D{YD&h*PFQ?)xRv~{s7c6SrL6T|Zzqt%1A@@z!Ipb>4+Ux}YqjP_Gy9 z+BSR`ju}-DiK@J|2?_j~K1Su^$C|?hRFAwC&letJXlnSHmO~!5=lijoH#@v&;{_NC9n8diu%sd z;L{&IK$H;cW|*z&6hUHGy!f-L6TO|E*T*!}K9B6$m;KmrlqFp)*OKaEtiEeE+#mg( z(a0~Gt4Bo*MnQwrqxj(w&=u3O)-mALU_L$`m-t(``uLu+{Y9!!CoT&iRmKp_&i$nX zH5J{EyM(BDyrv&Fd#F#&Z|K`N-15^P$2jbHp-GW@RTNq(V3>=CO#CcgEl; zZxaQE5KDT|vqX0K0p5HDUT8<5Hl4YLGxA~aQzc2`p}nUY>Qi!dh2JQOIJ(V*IxpDG z>0LN$<$Hr=Z^Cczz(GkgyJKGl1mzY@^S^M46b}!YQgNcp^zcd?G9msOAJ`7GzZnblweVskw@`@^Um*r z<8IHt)H%n8xfz7p4kU9f{Tg0TyYjXcxT!7nrYfF_+Na@0)Y}=#K#zn;_Pt8vrJ{)X zKpihUTAiHCDl?6yuvbkYgWdE?SJ&^3Z%~I{j?^F=ZepCJf-tvF!;#2G7PU3dIi9X3 z1D~Thc=vAz7W3uN`4OKNt#EbRQ<1Zim6PB<6`>Kn zSBb$%7oKrzS2M>wn9kA&-!)f<%e6lPxNlON)+eI zm?>5m7LpBm8CQ^!lnH33`F=!r8$U`*>JrqFKD(e97t0FVD!}##ZkfTX@@0AKzrud? zJVJy&M8R3T_MUz9>Q{!x@9}JiRg<~T?0=dwrg0Kg+%%)A> zLL6LZ7}1~P%;J8}uuL51N?WV@FQ>=v=T;R-5o z7MuQ&t~1JHrNJOM&^>Svt!b=w|I2w?HR1jl(U+gh;pLkBH;sFArV6M1@Q%VJ8vIF_ z#gK(PEqC;8mKfmIYYkAhHF4I(UlReoL)o6Q%ktB;EUr?6j zVb*1Rn4}nX2>e67lawQs74a!%6W!>R@Yi?9QN8BZ&0GOQIm9%EQj&%u9zJIDz5=G% zQONKOFc&rsl!vzlpZ!TYLoLS%$;cbo!&-i&TE^~*v12uxukO=4rror6aKycPDMa?0 zv+UhP)8}!HPif>cDr?3{a>#Ek<&m+o5Pm)@L#)JzXqBJMAagxMYiaRqY@g2D_45dnb_{tcE zW@mG!z57HG*%ZEGyOD%39bGFfngkKC^9%UrGq%N^#V>`s{5Y&SEAdlf_wf+NMM;nB z$uBa~nWH=t^j~*Gv-9bJEJY9bGD5=0w%=d}hunM8V5cc6gfjH~l2GQ&)NydnFnv5` zP5j1_X58j0N{7iZewg2KMbbJ*8~fg31j-1Bk2cxPgrq?zwTl?Y?nXr=Dvv8O z+Yl{XCJ-xZ6kp0D{)V*mG4edqd>SgZy8Dh%nBq2l#U<#l)S0Cu(Q_*8P)*hLE0eE4 z3rcURxe(f%yf~o z(@DgJ-<7Ujo$lMagk0+R7w(u7e1hxTRM*S5`y%#VKSp@aRaPe5+kCpVO|~3pVfEc7ey>E_h~;TX&^|`!Wh!QCk4c<|ZhAf$ z6{DJd=n(sj*?ZscqAnBzaZ)mt)&xc#jyx1_zfTq2L6TiZ^D*Rhz3K@Km5H0FFpLtepJbR@AEtQxRR%}r+5e@ zqM{^`N}T(zn71&A$<4u5$-Jy&No$N(AG@V$Lhdvvl58;NP{EuLug1Jy!|viG6h=lw?y<*!YZCzlGy@ z#L+7(rRVX&@k>d}sis5&1&#aZEh?~OI8+v(#cnl9g-Ay8XH{bt?O@~`i7!XkYA z)=x0o;$$oQVADJyrJ2g&j=w{byK0ckY*tRCLH>mepP}W@r^aundD0?wW~MPiq1plt zZi6G6T2PFD*=BmSyKUa*>h=9`+8$r+57Robiak|1&-MIfHQkR03vC!Nj82*NKP=W*PFOQU(xN%*U` zB=bgb5xU3jDi~jBgGSQFzmV`ww7t7(lNF|v@O2+6di7~s7A5ebf+UW-gx(Wl>~Z)d zXEgy1W7wbtye*Kk+;=;pQ#F~dhWj}Ic~gWvnEV-A zh+(Bvc>%gPX4)m$jY%s09u8_@!nN`dD^Gbh9K{Z=o2xvUX?`Ix(yVmBx$Akth9Sv) z*lKC-OJ(<{;07d5dK!bvH{gX`YAxke6M49T+}3OfkF$m3f?u*YHHZkg%_yj64lEb8 zW|pfYJ>8_fH&RLKUVYv_mvrN{+1KrDN@-_>nk=(tcP7gYFd1ou-6wcB-`#CtJQR8+ zf5&p9xQ~!3KLYe#?Z7XkX+`S}595F3 zzOqJ?{^+)*9?T4VHl=5(+R+)+i_m-&w)*oR>2$4v;8~(EHWl;>xaCQhU`l_SH*3vd zUPg;Hh`QP@x+s@xW_1>_*h0Z;o$q^DI&z|q_km(*+b@4pY7M#e=Haupy`N8}tZIH{ z6z-3zE`Ls%4xpCe^GsgEC-@#mV)$xy@7Y4r2R0X4$s!@C8cv=4FbBbd-ra)ip};!A zG>dY%Ni8qn_4oV^NkAR{ZaACSGPk7CaF2|7fskoMVJjARlk~year*P-j};6iquEuKQWu^EG(;o)o?u02x>a!Wxn2~G@Q#_H8R_bonz7t zFl#8s(_T5)Et}BniPg8_r1}WYoRK(fV6cglN6iQ8y*L*?=G^e7u0*EN_w`R)=n1h| zU>8&>vAi5qQTvf|TO1YJ);YxZi$Qt((`zFl_~;nr!MizzIN@PMkJ-rc(&pM+DdOR~ z;X~{1tqCEeiTZMZqV_*`^fWtZ&In!#WY=d4H`a?KHQkyUOdatO&7rw7#N}33e%Zp9 zERLD-xd+M#WeCl@inL+$p+hyf}OkeNQCFINSHx79NmP}P{!B~c@(bZ#N%S!!Fdp=Q#m-ytwC3@4=w^WI` zhdNgCO%Jk$6)xP#_KS!g4z4K2>hVZ)k7~~$Rly;@_pNt(0?a5bgmIZuh;QJsnbw=l z)jHk9`%#_ScsTZg#Y^&Y(tDmL$*fv- zw62HUQ$rj&F5K3mCe3LHc$R?!M)^KahexDeU$!ipyYtQ-X8%+S+}cY3Q(J&YQz zoSw;(1e1o$#D)6H^FVP$8!alxx_s1f&$R?)dkPbJbX;zPe1hbTj~KK^4B;l7KhD$W zQ#=fwHi#8o0p%VAT7~lG+#omT*YX6aZ)>3X&iYe*3ouSU)cDq~EAL_!bn!H-J_dv%SG_&wisez1-Wiz(ikxXzx`tNIYw03rg$~ORY>FK2nd=N%H8*t4|dr zJFqYQObT^YW#u}zy^zG!zuC%-MIlSsr52d|#37irq*U7j9H$pZmOAly^XlT}=F>_g zCJk)A^APQf7L3QY28_x!{Z%kr5m$=%O4 zm-ylDj`{QGZu{lc02Z6|Eo=1)lchP8XPZmd;JQ8>$&4K-JsNLD%S&b%b=5=s?U-!kDo-wB$6LWF-lsS z<)mVg@~*t$?4#5;e~aOTG5ijPkL!&T`_wQUNT};OdzpCKb13coT(5I0%V#7$;_9>% zM!~11zjP(PXsLafbuQfHI4RbbLGstoj>ZWmFh7pQFLRvXd#^#Wwp(b?{OeSJY;V?E zPlivQRmJm?ZPaqiwJ92Tb{=MhljI>@vC&0IHzRMcXQcRuV5x7TtK7Ww(<#w!lFe3} zOV6SCC*z(JnQwKm39iU~dnzpTcVQ)2kA3OcRU^15=p-2{*n6*D7BT)g0AKU6s8S-C zxXtMOqi-KQ7))XdPZ0uZl9zY6y$5ceXe-cO%3oa-I!W7j;egtsZ<(m2j2E`O>q=8v zsPA3SogG>7j9o2>x^ZJ8SDGF7HSpT$gMTEIMs^MBqnVLVS@WO%MBh)Fm2uqIE|}Hs z7Hs)1CPk@tYWCc^jaa14pWVnAl=soT6BrGHrFVS9lIq`|d7yBZ$S!G3q8mOu8f&2m zGfLn~6^&_?fJv|_S$6v~_VElFB6`l^h{is@Xsn-A9I6jLoQ0{0ik>l~>VN$#Y_2+s#~3)foCxL+Nq$QnsZO5B3n6r%CuW~2TAOqUS74iK0=dM_p1Y8cAxQ`A}fjY zW(S1yy>ScUV0g|A!)%o&T0dx}3SY>67alj8>z$j6zt~Fn-fji4d1c2OTTLb5Hyz>d zDSNZY&bcm)$4tfO!x<$vcgfF1_uuE;v#jLeuU|a>_~OTw?N5m8f@eUao>oKc zKzn!xtgFLta9<#3%gx}vD(;uycjO<8*N#`1ISU34s}oEf*oPXQPr4cRHTHa@S8v^Y z=09~Pf*_#c*CuV!p&6FfF4i#AJ9XVOO1*lDy>xXDnWI;=LhFEiB2lq0w2bi>vxy;a zkl2WTXQj^Ao8?I)S(3W@PO@(dyhZF(YVViCdGwN|?$x&omn8iga#IG@rPNY$e3#R$ zSHX`G4`@7D6ugXc;(9-?KaX&-pX9n>H}th$KZy#ZORT0~Ygc{cM!m1?G zu50y4r-EB5caJiOqC<(;niSK!QWTg=EX*%|c?WeZBuU^UCf013HuGJGHMF~S;K{u+ zE8>eZYL~+{HvH*Jgmk8KcMdIEU+FDix4qPPDeHMP%OXn zj^_tC;*ri1Wiv&H(ZgHxHqP5Z4Y^=O>vdkMQh1H??%L(l8@_jaeTsfEH)O;ps4zG= zOxge1MBWlB&sKgslQS_%X3;kH*8MIkivdP?(mn@-0^@f^Yx4{ydy|;T`%PQ&k~Qd- zCW(tq%gKnLA)I>u>{aQ3l){)N=2K&~U+Oh5tt!1YaG@jtJGudiB|4s$&6P9(suvUH z`&tOZRhgG?Wyh-QC62y_DAc5?)~$ci*t8>xOLj*s-QuYc&wEWNI~r9=U+0GpG7}ZG zb|1+9F3Hs`UFuL<>R!x?s4rd&9P0DdA!cAv}#+i`b-m$_D|~7${C_Z8*dl(L&1e4>02iLi|d{xr>zq& z7L{)}`R95jvoP{%=7A~&9*L|w@K3#~bI5o?U)CI}7&_yKMc?FB$WD^tqHNOA zsb`?Qx;zkeN*7ezPZSO~^IzNxy)Bb{p8DmTv#-RG>Jq^)C-3U5*}kVFD<3y;-S%P< zxb6t>ha*xdKd=Vk;tf_v9X+z8u?ul%&;GTNkbrEM`JRFuandH9_xcRKtux?2H268b zx4+cq`v+^N9lFRMzNXjb$(cVwafn$>M)NhkrdI`zHrAR6-lNNx_+sG8P4nr;=U1UL7ABYOt=5CvQ*Ar?^D!Cgfzf!oCqIG|OOo6v%>%G}*?8EC z_+XU>8VJTjF_8c)bn&LKf-b^z6^BcDG%+#vO2-p z%MY%e=uMF-@B=k56sU<;{&^!^8~Qfa`KYC(DQF7+rAu_a*!zctwK7dm*&kGtJ>`PQ z{Pwmnqhlhj}R(^Uzp6R-C5I#;x+e z&Y$ajZI$hXbT~e)Z+kRTbJ8{wQf(Vk(nXj3Niq71R6I6!*pqQOyV1U=HWBSm!~G{I ziEGJF!rvv|zl0J9zZI34!4SH7GtB0^`%5=8sK@MkhRg$TckOr@gjUm=G7wf~pV?V# zbDdKS-1ozq?i6-wm zYaM1}X^QK|yRITS4^<;Gu;KfS)6L2SA`{7`N^_(tVNt74xE+%-KGnqo$1Dm=B~=4N z&qLs=USQzU$tr&2UAJ4WKb~yMQJVOWSW`p6tIyB7?AO8_ilPUptv#ap`R-4*lcsh8 zB?h9pCg$%c)q^Zw`jGqY6P-;TeG`SHu6w;oclhP7VeqU(V}_uI{j4%yl*WhZh3Bo7 zG??mGNPJMZ3fC7B#&6lcdjq+fMiB*lBpIvR)HB%ho16|6(Y|-!;TP68Ki{j6l3dEh4^l@@m46$SjVdO*4k=uG*}ffXSD-uzNZBbArbq z;y1&dc&b{nWZk@7{zHZxNwd|^wOe9LTC_DGc*)J~lV;xkNX-s5akobOTwGET2jiH! zQgyGLr^GqTb=lyzPAxadJ+igCsjHE09Pyf_-Kz;lMI%`2pDJQHcaMY>oLTVF9)qn$ z8N+fhWXdDO4A5*t2Ne;r8$0B6%PX2?+v;bO(Vz4hVN!DA50_ zVQqjwz=Z)s?7y)89RMc&+aw6|@ZW3yuVYLQh*-?k1!50OnY!9v?}_!VWq-M$_x>O4 zf9&&ryKewMgT6o@HW<_u1@sIs2NdwN#_I-fK=Z}_D>G3U0t$x!GhhVtf1aHKKy!ff zK3&uC*g_p#u1CPl9S#M)F8NVpHx~!+pE1!bl&hr!2t;Sj)6coAtXY%?^cXb7Db+&c4lE=WX08la4XvSU8`Nhcz z2ton>prwd}i8|cT&C|?8NnRc-z|Skh%Wq~PA`G^K zyPAQ;fcrfG{_DFSa0kehc>$Ju%8L5(U@IgPW(A<+kxpJNa2s1!upqyH5D#z@19Mn$ zf;HS6T;Wzo7nldc1;!0laYQe+b#--;;NwFJ#*1{Z0We4>S2)rUB>}c_a)U#q1%Spc zBo4NAfgoT!uC^{P2oxnP0Cq(3csMzsJ0}FN@t?t;4&~^A22m(D0_=da;cdTNfxGfi)6r3qjce908Oo4B>=y z0pxIic%f;KPB2Fv8>AB$hz%Zlm=_>0Aj98*AQ+h8aX=#NA?Q5-4wiq#2kglMfkK>I z(OTgF%mqQfp?_z2Ea4FJ0bQ*AMJfm!_&yloiYoX65E8EsWLy%9ZCI z1V9dfI{c9t<%C|3mL8DK1;PU;2GFrB*vi#S8t^Q%%pG0ia0dzqaQGL%keARAPP7F+z|%-vjPl&NJpDL z01paC`L4EbN1JQ85il1U7~lebL;_Cz*KPm6Xs1Pi5ir19C^t)>7X$zoh$BF9Uljb0 zoe}PUILJS4#{+e{25b>9um=nsVb|cF;UC9wggAJ4!+21D@tojRC@>Ue>43Ddm*$rM ztOY?{9~*+acE-O`fSLdqQ7{KU>u`5~6oQl%2E!mO4qiOh%5eFk5M{-ddD z92x=)=zv6_9AGFE;86c8LYv;z1^Sl}6mV9EgR2*yODB{U+7yClQ~Vhto&PZmKmce9 zP%@hHKWwcmot==@fD-w^RxbYxU96<7T&w|%H4wwR{9tD*B*F>cBmxYbP_8g1;4mmx zh%1W6!v*e&j^jTNI*kAT+{pz3q#J1gUciN&EdK)t@q;1GJZKXEW&uWkm0^xHK;{rY z3k-NX@Xda(H_{OXgtQwFa@WoQEP`7BNyX9y>}>PLp8=NzjsO_L2JJL}M1Vg_i-@BK zaK}GX*Dl55Zs`u#2c18V?m%2yLC~}42O{!1VYo`)2LcN18^G>J2c(OW3mgH62Kb^Q z${O%a!9QpO1dzcK4cWRN5fH%i009&Zm;vI&;{kVsB0bO?9DvB==D&_S2R8%+K%wL8 zdMJ4RK00R#@}MzJNFWEGEP=3ecY^~74iFmc>Oe+9!$5la1N_Yg*Et!;-aO7uJWft1 z^vTf>U`iebbaHUGR^fl95a_1?j}rui`m+ik_)qrun}K-w@Bhgv=%kObMLJxE?sZB< z^95WE3UhFU0NbIry0#bk$$7S_DA<2ZBRg(5VKkZ@|-Ga3KEz z!GnUM0IVAd_D|;c2aSRN;qm`4=YWKuo%Y{!fDs*FK!8}eBGK97k4FOv18nx+!0X)d zcNXCec);H=kREve(*e}zQvoEv3I3!GbReT=(U$m&M|xaq5(;F_zvTaj4g7(MKW^jX zh0Y1U258el+|UX4KjHyyeXXGXB*}lG4+U5pI0afgXtl!JtpG)%hbZ@Jm0H7LKq&zj z{Q7Bv4kbsPKaP4GDgRg$f_~-$mXhZG*E8_1NAjSf8s>@uUl$F)fh>`(u1Ewh0O|=K z1YNFu5eQB6F@UXsSOF9P*y6ujC;+Ii2+^`!*Kg#2E}Q@i8bDt+EL~mxRH_&)o*?uE z0@0ydud7&Kc)f-Y1j0s-*?{5@UEQJ^4sfCA(N#2h68OImbkzl-K|x*7{6S!#CZj|D zkOP3W)qinBuL7vh9hw92-~M`s{}=Ez9RnbV6`BxeXerPaAmw#01BIECYQq(Axoh0npn5zqhgh1UFEwR>;4EXrA1_1#yGALV(@~0lV(e)6D;_ w&4GH}1>)ocl+XXwxZ!_(0bt8_MWPup0DtBL%>>O91Qf~EK#_bOsF4N!4@P6OWdHyG literal 0 HcmV?d00001 diff --git a/test/resources/h265_video.mp4.frame000006.pt b/test/resources/h265_video.mp4.frame000006.pt new file mode 100644 index 0000000000000000000000000000000000000000..1fda757caf921ba5ced35f8ad49c50fcfe2bfdcf GIT binary patch literal 50491 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 literal 0 HcmV?d00001 diff --git a/test/utils.py b/test/utils.py index 3e04c7658..16b1dfeff 100644 --- a/test/utils.py +++ b/test/utils.py @@ -152,3 +152,17 @@ def empty_chw_tensor(self) -> torch.Tensor: # When we start actually decoding audio-only files, we'll probably need to define # a TestAudio class with audio specific values. Until then, we only need a filename. NASA_AUDIO = TestContainerFile(filename="nasa_13013.mp4.audio.mp3", frames={}) + +H265_VIDEO = TestVideo( + filename="h265_video.mp4", + height=128, + width=128, + num_color_channels=3, + # TODO_OPEN_ISSUE Scott: improve the testing framework so that these values are loaded from a JSON + # file and not hardcoded. These values were copied over by hand from the JSON + # output from the following command: + # $ ffprobe -v error -hide_banner -select_streams v:1 -show_frames -of json test/resources/h265_video.mp4 > out.json + frames={ + 6: TestFrameInfo(pts_seconds=0.6, duration_seconds=0.1), + }, +)