@@ -572,8 +572,8 @@ class TestVideoEncoder:
572572 def decode (self , source = None ) -> torch .Tensor :
573573 return VideoDecoder (source ).get_frames_in_range (start = 0 , stop = 60 )
574574
575- def _get_codec_spec (self , file_path ):
576- """Helper function to get codec name from a video file using ffprobe."""
575+ def _get_video_metadata (self , file_path , fields ):
576+ """Helper function to get video metadata from a file using ffprobe."""
577577 result = subprocess .run (
578578 [
579579 "ffprobe" ,
@@ -582,16 +582,21 @@ def _get_codec_spec(self, file_path):
582582 "-select_streams" ,
583583 "v:0" ,
584584 "-show_entries" ,
585- "stream=codec_name " ,
585+ f "stream={ ',' . join ( fields ) } " ,
586586 "-of" ,
587- "default=noprint_wrappers=1:nokey=1 " ,
587+ "default=noprint_wrappers=1" ,
588588 str (file_path ),
589589 ],
590590 capture_output = True ,
591591 check = True ,
592592 text = True ,
593593 )
594- return result .stdout .strip ()
594+ metadata = {}
595+ for line in result .stdout .strip ().split ("\n " ):
596+ if "=" in line :
597+ key , value = line .split ("=" , 1 )
598+ metadata [key ] = value
599+ return metadata
595600
596601 @pytest .mark .parametrize ("method" , ("to_file" , "to_tensor" , "to_file_like" ))
597602 def test_bad_input_parameterized (self , tmp_path , method ):
@@ -1087,7 +1092,9 @@ def test_codec_parameter_utilized(self, tmp_path, format, codec_spec):
10871092 dest = str (tmp_path / f"output.{ format } " )
10881093
10891094 VideoEncoder (frames = frames , frame_rate = 30 ).to_file (dest = dest , codec = codec_spec )
1090- actual_codec_spec = self ._get_codec_spec (dest )
1095+ actual_codec_spec = self ._get_video_metadata (dest , fields = ["codec_name" ]).get (
1096+ "codec_name"
1097+ )
10911098 assert actual_codec_spec == codec_spec
10921099
10931100 @pytest .mark .skipif (
@@ -1123,61 +1130,51 @@ def test_codec_spec_vs_impl_equivalence(self, tmp_path, codec_spec, codec_impl):
11231130 dest = impl_output , codec = codec_impl
11241131 )
11251132
1126- assert self ._get_codec_spec (spec_output ) == codec_spec
1127- assert self ._get_codec_spec (impl_output ) == codec_spec
1133+ assert (
1134+ self ._get_video_metadata (spec_output , fields = ["codec_name" ]).get (
1135+ "codec_name"
1136+ )
1137+ == codec_spec
1138+ )
1139+ assert (
1140+ self ._get_video_metadata (impl_output , fields = ["codec_name" ]).get (
1141+ "codec_name"
1142+ )
1143+ == codec_spec
1144+ )
11281145
11291146 frames_spec = self .decode (spec_output ).data
11301147 frames_impl = self .decode (impl_output ).data
11311148 torch .testing .assert_close (frames_spec , frames_impl , rtol = 0 , atol = 0 )
11321149
1133- def get_video_metadata_from_file (self , file_path ):
1134- """Helper function to get video metadata from a file using ffprobe.
1135-
1136- Returns a dict with codec_name, profile, pix_fmt, etc.
1137- """
1138- result = subprocess .run (
1139- [
1140- "ffprobe" ,
1141- "-v" ,
1142- "error" ,
1143- "-select_streams" ,
1144- "v:0" ,
1145- "-show_entries" ,
1146- "stream=codec_name,profile,pix_fmt" ,
1147- "-of" ,
1148- "default=noprint_wrappers=1" ,
1149- str (file_path ),
1150- ],
1151- check = True ,
1152- capture_output = True ,
1153- text = True ,
1154- )
1155- # Parse output like "codec_name=h264\nprofile=Baseline\npix_fmt=yuv420p"
1156- metadata = {}
1157- for line in result .stdout .strip ().split ("\n " ):
1158- if "=" in line :
1159- key , value = line .split ("=" , 1 )
1160- metadata [key ] = value
1161- return metadata
1162-
11631150 @pytest .mark .skipif (in_fbcode (), reason = "ffprobe not available" )
1164- def test_codec_options_profile (self , tmp_path ):
1165- # Test that we can set the H.264 profile via codec_options
1166- # and validate it was used by checking with ffprobe.
1151+ @pytest .mark .parametrize (
1152+ "profile,colorspace,color_range" ,
1153+ [
1154+ ("baseline" , "bt709" , "tv" ),
1155+ ("main" , "bt470bg" , "pc" ),
1156+ ("high" , "fcc" , "pc" ),
1157+ ],
1158+ )
1159+ def test_codec_options_utilized (self , tmp_path , profile , colorspace , color_range ):
1160+ # Test setting profile, colorspace, and color_range via codec_options is utilized
11671161 source_frames = torch .zeros ((5 , 3 , 64 , 64 ), dtype = torch .uint8 )
11681162 encoder = VideoEncoder (frames = source_frames , frame_rate = 30 )
11691163
1170- # Encode with baseline profile (explicitly specified via codec_options)
1171- output_path = tmp_path / "output_baseline.mp4"
1164+ output_path = str (tmp_path / "output.mp4" )
11721165 encoder .to_file (
1173- dest = str (output_path ),
1174- codec_options = {"profile" : "baseline" },
1166+ dest = output_path ,
1167+ codec_options = {
1168+ "profile" : profile ,
1169+ "colorspace" : colorspace ,
1170+ "color_range" : color_range ,
1171+ },
11751172 )
1176-
1177- # Validate the profile was used
1178- metadata = self . get_video_metadata_from_file ( output_path )
1179- assert metadata . get ( "codec_name" ) == "h264"
1180- assert metadata . get ( "profile" ) in (
1181- "Baseline" ,
1182- "Constrained Baseline" ,
1183- ), f"Expected Baseline profile, got { metadata .get ('profile' ) } "
1173+ metadata = self . _get_video_metadata (
1174+ output_path ,
1175+ fields = [ "profile" , "color_space" , "color_range" ],
1176+ )
1177+ # Validate profile (case-insensitive, baseline is reported as "Constrained Baseline")
1178+ assert profile in metadata . get ( "profile" , "" ). lower ()
1179+ assert metadata . get ( "color_space" ) == colorspace
1180+ assert metadata .get ("color_range" ) == color_range
0 commit comments