1212import torch
1313from PIL import Image
1414
15+ from .utils import sanitize_filtergraph_expression
16+
1517# Run this script to update the resources used in unit tests. The resources are all derived
1618# from source media already checked into the repo.
1719
20+ SCRIPT_DIR = Path (__file__ ).resolve ().parent
21+ TORCHCODEC_PATH = SCRIPT_DIR .parent
22+ RESOURCES_DIR = TORCHCODEC_PATH / "test" / "resources"
23+
1824
1925def convert_image_to_tensor (image_path ):
2026 image_path = Path (image_path )
@@ -31,7 +37,18 @@ def convert_image_to_tensor(image_path):
3137 image_path .unlink ()
3238
3339
34- def get_frame_by_index (video_path , frame , output_path , stream ):
40+ def get_frame_by_index (video_path , frame , output_path , stream , filters = None ):
41+ # Note that we have an exlicit format conversion to rgb24 in our filtergraph specification,
42+ # which always happens BEFORE any of the filters that we receive as input. We do this to
43+ # ensure that the color conversion happens BEFORE the filters, matching the behavior of the
44+ # torchcodec filtergraph implementation.
45+ #
46+ # Not doing this would result in the color conversion happening AFTER the filters, which
47+ # would result in different color values for the same frame.
48+ filtergraph = f"select='eq(n\\ ,{ frame } )',format=rgb24"
49+ if filters is not None :
50+ filtergraph = filtergraph + f",{ filters } "
51+
3552 cmd = [
3653 "ffmpeg" ,
3754 "-y" ,
@@ -40,11 +57,11 @@ def get_frame_by_index(video_path, frame, output_path, stream):
4057 "-map" ,
4158 f"0:{ stream } " ,
4259 "-vf" ,
43- f"select=eq(n \\ , { frame } )" ,
44- "-vsync " ,
45- "vfr " ,
46- "-q:v " ,
47- "2 " ,
60+ filtergraph ,
61+ "-fps_mode " ,
62+ "passthrough " ,
63+ "-update " ,
64+ "1 " ,
4865 output_path ,
4966 ]
5067 subprocess .run (cmd , check = True )
@@ -65,14 +82,9 @@ def get_frame_by_timestamp(video_path, timestamp, output_path):
6582 subprocess .run (cmd , check = True )
6683
6784
68- def main ():
69- SCRIPT_DIR = Path (__file__ ).resolve ().parent
70- TORCHCODEC_PATH = SCRIPT_DIR .parent
71- RESOURCES_DIR = TORCHCODEC_PATH / "test" / "resources"
85+ def generate_nasa_13013_references ():
7286 VIDEO_PATH = RESOURCES_DIR / "nasa_13013.mp4"
7387
74- # Last generated with ffmpeg version 4.3
75- #
7688 # Note: The naming scheme used here must match the naming scheme used to load
7789 # tensors in ./utils.py.
7890 STREAMS = [0 , 3 ]
@@ -95,6 +107,16 @@ def main():
95107 get_frame_by_timestamp (VIDEO_PATH , timestamp , output_bmp )
96108 convert_image_to_tensor (output_bmp )
97109
110+ # Extract frames with specific filters. We have tests that assume these exact filters.
111+ FRAMES = [0 , 15 , 200 , 389 ]
112+ crop_filter = "crop=300:200:50:35:exact=1"
113+ for frame in FRAMES :
114+ output_bmp = f"{ VIDEO_PATH } .{ sanitize_filtergraph_expression (crop_filter )} .stream3.frame{ frame :06d} .bmp"
115+ get_frame_by_index (VIDEO_PATH , frame , output_bmp , stream = 3 , filters = crop_filter )
116+ convert_image_to_tensor (output_bmp )
117+
118+
119+ def generate_h265_video_references ():
98120 # This video was generated by running the following:
99121 # conda install -c conda-forge x265
100122 # ./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
@@ -107,6 +129,8 @@ def main():
107129 get_frame_by_index (VIDEO_PATH , frame , output_bmp , stream = 0 )
108130 convert_image_to_tensor (output_bmp )
109131
132+
133+ def generate_av1_video_references ():
110134 # This video was generated by running the following:
111135 # ffmpeg -f lavfi -i testsrc=duration=5:size=640x360:rate=25,format=yuv420p -c:v libaom-av1 -crf 30 -colorspace bt709 -color_primaries bt709 -color_trc bt709 av1_video.mkv
112136 # Note that this video only has 1 stream, at index 0.
@@ -119,5 +143,11 @@ def main():
119143 convert_image_to_tensor (output_bmp )
120144
121145
146+ def main ():
147+ generate_nasa_13013_references ()
148+ generate_h265_video_references ()
149+ generate_av1_video_references ()
150+
151+
122152if __name__ == "__main__" :
123153 main ()
0 commit comments