11import abc
22import json
3- import os
43import subprocess
4+ import urllib .request
55from concurrent .futures import ThreadPoolExecutor , wait
66from itertools import product
7+ from pathlib import Path
78
89import matplotlib .pyplot as plt
910import numpy as np
@@ -341,6 +342,7 @@ def generate_video(command):
341342def generate_videos (
342343 resolutions ,
343344 encodings ,
345+ patterns ,
344346 fpses ,
345347 gop_sizes ,
346348 durations ,
@@ -352,23 +354,25 @@ def generate_videos(
352354 video_count = 0
353355
354356 futures = []
355- for resolution , duration , fps , gop_size , encoding , pix_fmt in product (
356- resolutions , durations , fpses , gop_sizes , encodings , pix_fmts
357+ for resolution , duration , fps , gop_size , encoding , pattern , pix_fmt in product (
358+ resolutions , durations , fpses , gop_sizes , encodings , patterns , pix_fmts
357359 ):
358- outfile = f"{ output_dir } /{ resolution } _{ duration } s_{ fps } fps_{ gop_size } gop_{ encoding } _{ pix_fmt } .mp4"
360+ outfile = f"{ output_dir } /{ pattern } _ { resolution } _{ duration } s_{ fps } fps_{ gop_size } gop_{ encoding } _{ pix_fmt } .mp4"
359361 command = [
360362 ffmpeg_cli ,
361363 "-y" ,
362364 "-f" ,
363365 "lavfi" ,
364366 "-i" ,
365- f"color=c=blue:s={ resolution } :d={ duration } " ,
367+ f"{ pattern } =s={ resolution } " ,
368+ "-t" ,
369+ str (duration ),
366370 "-c:v" ,
367371 encoding ,
368372 "-r" ,
369- f" { fps } " ,
373+ str ( fps ) ,
370374 "-g" ,
371- f" { gop_size } " ,
375+ str ( gop_size ) ,
372376 "-pix_fmt" ,
373377 pix_fmt ,
374378 outfile ,
@@ -383,6 +387,11 @@ def generate_videos(
383387 print (f"Generated { video_count } videos" )
384388
385389
390+ def retrieve_videos (urls_and_dest_paths ):
391+ for url , path in urls_and_dest_paths :
392+ urllib .request .urlretrieve (url , path )
393+
394+
386395def plot_data (df_data , plot_path ):
387396 # Creating the DataFrame
388397 df = pd .DataFrame (df_data )
@@ -411,7 +420,7 @@ def plot_data(df_data, plot_path):
411420 nrows = len (unique_videos ),
412421 ncols = max_combinations ,
413422 figsize = (max_combinations * 6 , len (unique_videos ) * 4 ),
414- sharex = True ,
423+ sharex = False ,
415424 sharey = True ,
416425 )
417426
@@ -430,16 +439,19 @@ def plot_data(df_data, plot_path):
430439 ax = axes [row , col ] # Select the appropriate axis
431440
432441 # Set the title for the subplot
433- base_video = os . path . basename ( video )
442+ base_video = Path ( video ). name . removesuffix ( ".mp4" )
434443 ax .set_title (
435- f"video={ base_video } \n decode_pattern={ vcount } x { vtype } " , fontsize = 12
444+ f"video={ base_video } \n decode_pattern={ vcount } x { vtype } " , fontsize = 10
436445 )
437446
438447 # Plot bars with error bars
439448 ax .barh (
440449 group ["decoder" ],
441- group ["fps" ],
442- xerr = [group ["fps" ] - group ["fps_p75" ], group ["fps_p25" ] - group ["fps" ]],
450+ group ["fps_median" ],
451+ xerr = [
452+ group ["fps_median" ] - group ["fps_p75" ],
453+ group ["fps_p25" ] - group ["fps_median" ],
454+ ],
443455 color = [colors (i ) for i in range (len (group ))],
444456 align = "center" ,
445457 capsize = 5 ,
@@ -449,28 +461,11 @@ def plot_data(df_data, plot_path):
449461 # Set the labels
450462 ax .set_xlabel ("FPS" )
451463
452- # No need for y-axis label past the plot on the far left
453- if col == 0 :
454- ax .set_ylabel ("Decoder" )
455-
456464 # Remove any empty subplots for videos with fewer combinations
457465 for row in range (len (unique_videos )):
458466 for col in range (video_type_combinations [unique_videos [row ]], max_combinations ):
459467 fig .delaxes (axes [row , col ])
460468
461- # If we just call fig.legend, we'll get duplicate labels, as each label appears on
462- # each subplot. We take advantage of dicts having unique keys to de-dupe.
463- handles , labels = plt .gca ().get_legend_handles_labels ()
464- unique_labels = dict (zip (labels , handles ))
465-
466- # Reverse the order of the handles and labels to match the order of the bars
467- fig .legend (
468- handles = reversed (unique_labels .values ()),
469- labels = reversed (unique_labels .keys ()),
470- frameon = True ,
471- loc = "right" ,
472- )
473-
474469 # Adjust layout to avoid overlap
475470 plt .tight_layout ()
476471
@@ -486,7 +481,7 @@ def get_metadata(video_file_path: str) -> VideoStreamMetadata:
486481
487482def run_benchmarks (
488483 decoder_dict : dict [str , AbstractDecoder ],
489- video_files_paths : list [str ],
484+ video_files_paths : list [Path ],
490485 num_samples : int ,
491486 num_sequential_frames_from_start : list [int ],
492487 min_runtime_seconds : float ,
@@ -526,7 +521,7 @@ def run_benchmarks(
526521 seeked_result = benchmark .Timer (
527522 stmt = "decoder.get_frames_from_video(video_file, pts_list)" ,
528523 globals = {
529- "video_file" : video_file_path ,
524+ "video_file" : str ( video_file_path ) ,
530525 "pts_list" : pts_list ,
531526 "decoder" : decoder ,
532527 },
@@ -539,22 +534,22 @@ def run_benchmarks(
539534 )
540535 df_item = {}
541536 df_item ["decoder" ] = decoder_name
542- df_item ["video" ] = video_file_path
537+ df_item ["video" ] = str ( video_file_path )
543538 df_item ["description" ] = results [- 1 ].description
544539 df_item ["frame_count" ] = num_samples
545540 df_item ["median" ] = results [- 1 ].median
546541 df_item ["iqr" ] = results [- 1 ].iqr
547542 df_item ["type" ] = f"{ kind } :seek()+next()"
548- df_item ["fps " ] = 1.0 * num_samples / results [- 1 ].median
549- df_item ["fps_p75" ] = 1.0 * num_samples / results [- 1 ]._p75
550- df_item ["fps_p25" ] = 1.0 * num_samples / results [- 1 ]._p25
543+ df_item ["fps_median " ] = num_samples / results [- 1 ].median
544+ df_item ["fps_p75" ] = num_samples / results [- 1 ]._p75
545+ df_item ["fps_p25" ] = num_samples / results [- 1 ]._p25
551546 df_data .append (df_item )
552547
553548 for num_consecutive_nexts in num_sequential_frames_from_start :
554549 consecutive_frames_result = benchmark .Timer (
555550 stmt = "decoder.get_consecutive_frames_from_video(video_file, consecutive_frames_to_extract)" ,
556551 globals = {
557- "video_file" : video_file_path ,
552+ "video_file" : str ( video_file_path ) ,
558553 "consecutive_frames_to_extract" : num_consecutive_nexts ,
559554 "decoder" : decoder ,
560555 },
@@ -569,15 +564,15 @@ def run_benchmarks(
569564 )
570565 df_item = {}
571566 df_item ["decoder" ] = decoder_name
572- df_item ["video" ] = video_file_path
567+ df_item ["video" ] = str ( video_file_path )
573568 df_item ["description" ] = results [- 1 ].description
574569 df_item ["frame_count" ] = num_consecutive_nexts
575570 df_item ["median" ] = results [- 1 ].median
576571 df_item ["iqr" ] = results [- 1 ].iqr
577572 df_item ["type" ] = "next()"
578- df_item ["fps " ] = 1.0 * num_consecutive_nexts / results [- 1 ].median
579- df_item ["fps_p75" ] = 1.0 * num_consecutive_nexts / results [- 1 ]._p75
580- df_item ["fps_p25" ] = 1.0 * num_consecutive_nexts / results [- 1 ]._p25
573+ df_item ["fps_median " ] = num_consecutive_nexts / results [- 1 ].median
574+ df_item ["fps_p75" ] = num_consecutive_nexts / results [- 1 ]._p75
575+ df_item ["fps_p25" ] = num_consecutive_nexts / results [- 1 ]._p25
581576 df_data .append (df_item )
582577
583578 first_video_file_path = video_files_paths [0 ]
@@ -587,7 +582,7 @@ def run_benchmarks(
587582 creation_result = benchmark .Timer (
588583 stmt = "create_torchcodec_decoder_from_file(video_file)" ,
589584 globals = {
590- "video_file" : first_video_file_path ,
585+ "video_file" : str ( first_video_file_path ) ,
591586 "create_torchcodec_decoder_from_file" : create_torchcodec_decoder_from_file ,
592587 },
593588 label = f"video={ first_video_file_path } { metadata_label } " ,
0 commit comments