77import argparse
88import importlib .resources
99import os
10+ import typing
11+ from dataclasses import dataclass , field
1012from pathlib import Path
1113
1214from benchmark_decoders_library import (
13- DecordNonBatchDecoderAccurateSeek ,
15+ AbstractDecoder ,
16+ DecordAccurate ,
17+ DecordAccurateBatch ,
1418 plot_data ,
1519 run_benchmarks ,
1620 TorchAudioDecoder ,
1721 TorchCodecCore ,
1822 TorchCodecCoreBatch ,
1923 TorchCodecCoreCompiled ,
24+ TorchCodecCoreNonBatch ,
2025 TorchCodecPublic ,
2126 TorchVision ,
2227)
2328
2429
30+ @dataclass
31+ class DecoderKind :
32+ display_name : str
33+ kind : typing .Type [AbstractDecoder ]
34+ default_options : dict [str , str ] = field (default_factory = dict )
35+
36+
37+ decoder_registry = {
38+ "decord" : DecoderKind ("DecordAccurate" , DecordAccurate ),
39+ "decord_batch" : DecoderKind ("DecordAccurateBatch" , DecordAccurateBatch ),
40+ "torchcodec_core" : DecoderKind ("TorchCodecCore" , TorchCodecCore ),
41+ "torchcodec_core_batch" : DecoderKind ("TorchCodecCoreBatch" , TorchCodecCoreBatch ),
42+ "torchcodec_core_nonbatch" : DecoderKind (
43+ "TorchCodecCoreNonBatch" , TorchCodecCoreNonBatch
44+ ),
45+ "torchcodec_core_compiled" : DecoderKind (
46+ "TorchCodecCoreCompiled" , TorchCodecCoreCompiled
47+ ),
48+ "torchcodec_public" : DecoderKind ("TorchCodecPublic" , TorchCodecPublic ),
49+ "torchvision" : DecoderKind (
50+ # We don't compare against TorchVision's "pyav" backend because it doesn't support
51+ # accurate seeks.
52+ "TorchVision[backend=video_reader]" ,
53+ TorchVision ,
54+ {"backend" : "video_reader" },
55+ ),
56+ "torchaudio" : DecoderKind ("TorchAudio" , TorchAudioDecoder ),
57+ }
58+
59+
2560def in_fbcode () -> bool :
2661 return "FB_PAR_RUNTIME_FILES" in os .environ
2762
@@ -35,6 +70,16 @@ def get_test_resource_path(filename: str) -> str:
3570 return str (Path (__file__ ).parent / f"../../test/resources/{ filename } " )
3671
3772
73+ def parse_options_code (options_code : str ) -> dict [str , str ]:
74+ options = {}
75+ for item in options_code .split ("+" ):
76+ if item .strip () == "" :
77+ continue
78+ k , v = item .split ("=" )
79+ options [k ] = v
80+ return options
81+
82+
3883def main () -> None :
3984 """Benchmarks the performance of a few video decoders"""
4085
@@ -67,11 +112,18 @@ def main() -> None:
67112 "--decoders" ,
68113 help = (
69114 "Comma-separated list of decoders to benchmark. "
70- "Choices are torchcodec, torchaudio, torchvision, decord, tcoptions:num_threads=1+color_conversion_library=filtergraph, torchcodec_compiled"
71- "For torchcodec, you can specify options with tcoptions:<plus-separated-options>. "
115+ "Choices are: " + ", " .join (decoder_registry .keys ()) + ". "
116+ "To specify options, append a ':' and then value pairs seperated by a '+'. "
117+ "For example, torchcodec_core:num_threads=1+color_conversion_library=filtergraph."
72118 ),
73119 type = str ,
74- default = "decord,tcoptions:,torchvision,torchaudio,torchcodec_compiled,torchcodec_public,tcoptions:num_threads=1,tcbatchoptions:" ,
120+ default = (
121+ "decord,decord_batch,"
122+ "torchvision,"
123+ "torchaudio,"
124+ "torchcodec_core,torchcodec_core:num_threads=1,torchcodec_core_batch,torchcodec_core_nonbatch,"
125+ "torchcodec_public"
126+ ),
75127 )
76128 parser .add_argument (
77129 "--bm_video_dir" ,
@@ -87,51 +139,26 @@ def main() -> None:
87139 )
88140
89141 args = parser .parse_args ()
90- decoders = set (args .decoders .split ("," ))
142+ specified_decoders = set (args .decoders .split ("," ))
91143
92144 # These are the PTS values we want to extract from the small video.
93145 num_uniform_samples = 10
94146
95- decoder_dict = {}
96- for decoder in decoders :
97- if decoder == "decord" :
98- decoder_dict ["DecordNonBatchDecoderAccurateSeek" ] = (
99- DecordNonBatchDecoderAccurateSeek ()
100- )
101- elif decoder == "torchcodec" :
102- decoder_dict ["TorchCodecCore:" ] = TorchCodecCore ()
103- elif decoder == "torchcodec_compiled" :
104- decoder_dict ["TorchCodecCoreCompiled" ] = TorchCodecCoreCompiled ()
105- elif decoder == "torchcodec_public" :
106- decoder_dict ["TorchCodecPublic" ] = TorchCodecPublic ()
107- elif decoder == "torchvision" :
108- decoder_dict ["TorchVision[backend=video_reader]" ] = (
109- # We don't compare TorchVision's "pyav" backend because it doesn't support
110- # accurate seeks.
111- TorchVision ("video_reader" )
112- )
113- elif decoder == "torchaudio" :
114- decoder_dict ["TorchAudioDecoder" ] = TorchAudioDecoder ()
115- elif decoder .startswith ("tcbatchoptions:" ):
116- options = decoder [len ("tcbatchoptions:" ) :]
117- kwargs_dict = {}
118- for item in options .split ("+" ):
119- if item .strip () == "" :
120- continue
121- k , v = item .split ("=" )
122- kwargs_dict [k ] = v
123- decoder_dict ["TorchCodecCoreBatch" + options ] = TorchCodecCoreBatch (
124- ** kwargs_dict
125- )
126- elif decoder .startswith ("tcoptions:" ):
127- options = decoder [len ("tcoptions:" ) :]
128- kwargs_dict = {}
129- for item in options .split ("+" ):
130- if item .strip () == "" :
131- continue
132- k , v = item .split ("=" )
133- kwargs_dict [k ] = v
134- decoder_dict ["TorchCodecCore:" + options ] = TorchCodecCore (** kwargs_dict )
147+ decoders_to_run = {}
148+ for decoder in specified_decoders :
149+ if ":" in decoder :
150+ decoder , _ , options_code = decoder .partition (":" )
151+ assert decoder in decoder_registry , f"Unknown decoder: { decoder } "
152+ display = decoder_registry [decoder ].display_name + ":" + options_code
153+ options = parse_options_code (options_code )
154+ else :
155+ assert decoder in decoder_registry , f"Unknown decoder: { decoder } "
156+ display = decoder_registry [decoder ].display_name
157+ options = decoder_registry [decoder ].default_options
158+
159+ kind = decoder_registry [decoder ].kind
160+ decoders_to_run [display ] = kind (** options )
161+
135162 video_paths = args .bm_video_paths .split ("," )
136163 if args .bm_video_dir :
137164 video_paths = []
@@ -140,7 +167,7 @@ def main() -> None:
140167 video_paths .append (entry .path )
141168
142169 df_data = run_benchmarks (
143- decoder_dict ,
170+ decoders_to_run ,
144171 video_paths ,
145172 num_uniform_samples ,
146173 num_sequential_frames_from_start = [1 , 10 , 100 ],
0 commit comments