134134CONCURRENT_ENCODER_COUNT = 8
135135CONCURRENT_DECODER_COUNT = 16
136136
137- def _run_ffmpeg_command (command ):
137+ def _run_ffmpeg_command (command , verbose ):
138138 """Executes an FFmpeg command and returns True on success, False on failure."""
139139 try :
140+ stdout = subprocess .PIPE if verbose else subprocess .DEVNULL
141+ stderr = subprocess .PIPE if verbose else subprocess .DEVNULL
140142 result = subprocess .run (
141143 command ,
142144 check = True ,
143- stdout = subprocess .DEVNULL ,
144- stderr = subprocess .DEVNULL ,
145+ stdout = stdout ,
146+ stderr = stderr ,
147+ text = True
145148 )
146- return result .returncode == 0
147- except (subprocess .CalledProcessError , FileNotFoundError ):
148- return False
149+ return (result .returncode == 0 , result .stdout , result .stderr )
150+ except subprocess .CalledProcessError as e :
151+ return (False , e .stdout , e .stderr )
152+ except FileNotFoundError :
153+ return (False , "" , "FFmpeg executable not found" )
149154
150155def _run_encoder_test_single (test_data ):
151156 """Runs a single encoder test and returns the result."""
152- codec , encoder , res_name , res_size , test_dir = test_data
157+ codec , encoder , res_name , res_size , test_dir , verbose = test_data
153158 file_ext = ".webm" if codec in ["vp8" , "vp9" ] else ".mp4"
154159 output_file = os .path .join (test_dir , f"{ encoder } _{ res_name } { file_ext } " )
155160
@@ -170,11 +175,24 @@ def _run_encoder_test_single(test_data):
170175 command .insert (9 , "-dual_gfx" )
171176 command .insert (10 , "0" )
172177
173- status = "succeeded" if _run_ffmpeg_command (command ) else "failed"
178+ if verbose : # if verbose then replace loglevel to verbose
179+ command [2 ] = "error"
180+
181+ success , stdout , stderr = _run_ffmpeg_command (command , verbose )
182+ status = "succeeded" if success else "failed"
183+
184+ if verbose :
185+ if stdout :
186+ print (f"Output:\n { stdout } " )
187+ if stderr :
188+ print (f"Error Output:\n { stderr } " )
189+ print (f"Test Result: { status } " )
190+
174191 title = ENCODER_TITLES .get ((encoder , codec ), f"{ encoder .upper ()} Encoder:" )
175192 return title , res_name , status
176193
177- def _run_encoder_tests (test_dir , max_workers ):
194+
195+ def _run_encoder_tests (test_dir , max_workers , verbose ):
178196 """Runs hardware encoder tests using a thread pool."""
179197 results = defaultdict (dict )
180198
@@ -184,7 +202,7 @@ def _run_encoder_tests(test_dir, max_workers):
184202 for codec , info in ENCODERS .items ():
185203 for encoder in info ['hw_encoders' ]:
186204 for res_name , res_size in RESOLUTIONS .items ():
187- tasks .append ((codec , encoder , res_name , res_size , test_dir ))
205+ tasks .append ((codec , encoder , res_name , res_size , test_dir , verbose ))
188206
189207 with ThreadPoolExecutor (max_workers = max_workers ) as executor :
190208 futures = [executor .submit (_run_encoder_test_single , task ) for task in tasks ]
@@ -197,7 +215,7 @@ def _run_encoder_tests(test_dir, max_workers):
197215
198216def _run_decoder_test_single (test_data ):
199217 """Runs a single decoder test and returns the result."""
200- codec , hw_decoder , res_name , res_size , test_dir = test_data
218+ codec , hw_decoder , res_name , res_size , test_dir , verbose = test_data
201219 file_ext = ".webm" if codec in ["vp8" , "vp9" ] else ".mp4"
202220 test_file_path = os .path .join (test_dir , f"{ codec } _{ res_name } { file_ext } " )
203221
@@ -216,7 +234,7 @@ def _run_decoder_test_single(test_data):
216234 "-frames:v" , "1" , "-c:v" , cpu_lib , "-pixel_format" , "yuv420p" ,
217235 test_file_path ,
218236 ]
219- if not _run_ffmpeg_command (command ):
237+ if not _run_ffmpeg_command (command , verbose ):
220238 title = DECODER_TITLES .get ((hw_decoder , codec ), f"{ hw_decoder .upper ()} Decoder:" )
221239 return title , res_name , "skipped"
222240
@@ -250,13 +268,25 @@ def _run_decoder_test_single(test_data):
250268 "-c:v" , "libx264" , "-preset" , "ultrafast" ,
251269 "-f" , "null" , "null" ,
252270 ]
253-
254- status = "succeeded" if _run_ffmpeg_command (command ) else "failed"
271+
272+ if verbose : # if verbose then replace loglevel to verbose
273+ command [2 ] = "error"
274+
275+ success , stdout , stderr = _run_ffmpeg_command (command , verbose )
276+ status = "succeeded" if success else "failed"
277+
278+ if verbose :
279+ if stdout :
280+ print (f"Output:\n { stdout } " )
281+ if stderr :
282+ print (f"Error Output:\n { stderr } " )
283+ print (f"Test Result: { status } " )
284+
255285 title = DECODER_TITLES .get ((hw_decoder , codec ), f"{ hw_decoder .upper ()} Decoder:" )
256286 return title , res_name , status
257287
258288
259- def _run_decoder_tests (test_dir , max_workers ):
289+ def _run_decoder_tests (test_dir , max_workers , verbose ):
260290 """Runs hardware decoder tests using a thread pool."""
261291 results = defaultdict (dict )
262292
@@ -266,8 +296,8 @@ def _run_decoder_tests(test_dir, max_workers):
266296 for codec , info in DECODERS .items ():
267297 for hw_decoder in info ['hw_decoders' ]:
268298 for res_name , res_size in RESOLUTIONS .items ():
269- tasks .append ((codec , hw_decoder , res_name , res_size , test_dir ))
270-
299+ tasks .append ((codec , hw_decoder , res_name , res_size , test_dir , verbose ))
300+
271301 with ThreadPoolExecutor (max_workers = max_workers ) as executor :
272302 futures = [executor .submit (_run_decoder_test_single , task ) for task in tasks ]
273303
@@ -297,7 +327,7 @@ def _print_summary_table(results):
297327
298328 res_width = max (len (res ) for res in resolutions )
299329 row_header_width = max ([_get_display_width (t ) for t in results .keys ()] + [20 , _get_display_width ("Decoder" ), _get_display_width ("Encoder" )])
300-
330+
301331 if decoder_titles :
302332 print ("\n " + "-" * (row_header_width + 3 + (res_width + 3 ) * len (resolutions )))
303333 header_text = "Decoder"
@@ -308,7 +338,7 @@ def _print_summary_table(results):
308338 header_row += f" { res .center (res_width )} |"
309339 print (header_row )
310340 print ("-" * (row_header_width + 3 + (res_width + 3 ) * len (resolutions )))
311-
341+
312342 for title in decoder_titles :
313343 padding_needed = row_header_width - _get_display_width (title )
314344 row_string = f"| { title } { ' ' * padding_needed } |"
@@ -332,7 +362,7 @@ def _print_summary_table(results):
332362 header_row += f" { res .center (res_width )} |"
333363 print (header_row )
334364 print ("-" * (row_header_width + 3 + (res_width + 3 ) * len (resolutions )))
335-
365+
336366 for title in encoder_titles :
337367 padding_needed = row_header_width - _get_display_width (title )
338368 row_string = f"| { title } { ' ' * padding_needed } |"
@@ -361,8 +391,8 @@ def run_all_tests(args):
361391 shutil .rmtree (temp_dir )
362392 os .makedirs (temp_dir )
363393
364- encoder_results = _run_encoder_tests (temp_dir , args .encoder_count )
365- decoder_results = _run_decoder_tests (temp_dir , args .decoder_count )
394+ encoder_results = _run_encoder_tests (temp_dir , args .encoder_count , args . verbose )
395+ decoder_results = _run_decoder_tests (temp_dir , args .decoder_count , args . verbose )
366396
367397 all_results = {}
368398 all_results .update (encoder_results )
@@ -424,6 +454,12 @@ def main():
424454 help = "Show program's version number and exit."
425455 )
426456
457+ parser .add_argument (
458+ '--verbose' ,
459+ action = 'store_true' ,
460+ help = 'Print detailed information for each test'
461+ )
462+
427463 args = parser .parse_args ()
428464 run_all_tests (args )
429465
0 commit comments