55# LICENSE file in the root directory of this source tree.
66
77import functools
8+ from fractions import Fraction
89
910import pytest
1011
@@ -81,6 +82,7 @@ def test_get_metadata(metadata_getter):
8182 assert best_video_stream_metadata .begin_stream_seconds_from_header == 0
8283 assert best_video_stream_metadata .bit_rate == 128783
8384 assert best_video_stream_metadata .average_fps == pytest .approx (29.97 , abs = 0.001 )
85+ assert best_video_stream_metadata .pixel_aspect_ratio is None
8486 assert best_video_stream_metadata .codec == "h264"
8587 assert best_video_stream_metadata .num_frames_from_content == (
8688 390 if with_scan else None
@@ -119,7 +121,7 @@ def test_get_metadata_audio_file(metadata_getter):
119121
120122@pytest .mark .parametrize (
121123 "num_frames_from_header, num_frames_from_content, expected_num_frames" ,
122- [(None , 10 , 10 ), (10 , None , 10 ), (None , None , None )],
124+ [(10 , 20 , 20 ), (None , 10 , 10 ), (10 , None , 10 )],
123125)
124126def test_num_frames_fallback (
125127 num_frames_from_header , num_frames_from_content , expected_num_frames
@@ -137,12 +139,100 @@ def test_num_frames_fallback(
137139 width = 123 ,
138140 height = 321 ,
139141 average_fps_from_header = 30 ,
142+ pixel_aspect_ratio = Fraction (1 , 1 ),
140143 stream_index = 0 ,
141144 )
142145
143146 assert metadata .num_frames == expected_num_frames
144147
145148
149+ @pytest .mark .parametrize (
150+ "average_fps_from_header, duration_seconds_from_header, expected_num_frames" ,
151+ [(60 , 10 , 600 ), (60 , None , None ), (None , 10 , None ), (None , None , None )],
152+ )
153+ def test_calculate_num_frames_using_fps_and_duration (
154+ average_fps_from_header , duration_seconds_from_header , expected_num_frames
155+ ):
156+ """Check that if num_frames_from_content and num_frames_from_header are missing,
157+ `.num_frames` is calculated using average_fps_from_header and duration_seconds_from_header
158+ """
159+ metadata = VideoStreamMetadata (
160+ duration_seconds_from_header = duration_seconds_from_header ,
161+ bit_rate = 123 ,
162+ num_frames_from_header = None , # None to test calculating num_frames
163+ num_frames_from_content = None , # None to test calculating num_frames
164+ begin_stream_seconds_from_header = 0 ,
165+ begin_stream_seconds_from_content = 0 ,
166+ end_stream_seconds_from_content = 4 ,
167+ codec = "whatever" ,
168+ width = 123 ,
169+ height = 321 ,
170+ average_fps_from_header = average_fps_from_header ,
171+ stream_index = 0 ,
172+ )
173+
174+ assert metadata .num_frames == expected_num_frames
175+
176+
177+ @pytest .mark .parametrize (
178+ "duration_seconds_from_header, begin_stream_seconds_from_content, end_stream_seconds_from_content, expected_duration_seconds" ,
179+ [(60 , 5 , 20 , 15 ), (60 , 1 , None , 60 ), (60 , None , 1 , 60 ), (None , 0 , 10 , 10 )],
180+ )
181+ def test_duration_seconds_fallback (
182+ duration_seconds_from_header ,
183+ begin_stream_seconds_from_content ,
184+ end_stream_seconds_from_content ,
185+ expected_duration_seconds ,
186+ ):
187+ """Check that using begin_stream_seconds_from_content and end_stream_seconds_from_content to calculate `.duration_seconds`
188+ has priority. If either value is missing, duration_seconds_from_header is used.
189+ """
190+ metadata = VideoStreamMetadata (
191+ duration_seconds_from_header = duration_seconds_from_header ,
192+ bit_rate = 123 ,
193+ num_frames_from_header = 5 ,
194+ num_frames_from_content = 10 ,
195+ begin_stream_seconds_from_header = 0 ,
196+ begin_stream_seconds_from_content = begin_stream_seconds_from_content ,
197+ end_stream_seconds_from_content = end_stream_seconds_from_content ,
198+ codec = "whatever" ,
199+ width = 123 ,
200+ height = 321 ,
201+ average_fps_from_header = 5 ,
202+ stream_index = 0 ,
203+ )
204+
205+ assert metadata .duration_seconds == expected_duration_seconds
206+
207+
208+ @pytest .mark .parametrize (
209+ "num_frames_from_header, average_fps_from_header, expected_duration_seconds" ,
210+ [(100 , 10 , 10 ), (100 , None , None ), (None , 10 , None ), (None , None , None )],
211+ )
212+ def test_calculate_duration_seconds_using_fps_and_num_frames (
213+ num_frames_from_header , average_fps_from_header , expected_duration_seconds
214+ ):
215+ """Check that duration_seconds is calculated using average_fps_from_header and num_frames_from_header
216+ if duration_seconds_from_header is missing.
217+ """
218+ metadata = VideoStreamMetadata (
219+ duration_seconds_from_header = None , # None to test calculating duration_seconds
220+ bit_rate = 123 ,
221+ num_frames_from_header = num_frames_from_header ,
222+ num_frames_from_content = 10 ,
223+ begin_stream_seconds_from_header = 0 ,
224+ begin_stream_seconds_from_content = None , # None to test calculating duration_seconds
225+ end_stream_seconds_from_content = None , # None to test calculating duration_seconds
226+ codec = "whatever" ,
227+ width = 123 ,
228+ height = 321 ,
229+ average_fps_from_header = average_fps_from_header ,
230+ stream_index = 0 ,
231+ )
232+ assert metadata .duration_seconds_from_header is None
233+ assert metadata .duration_seconds == expected_duration_seconds
234+
235+
146236def test_repr ():
147237 # Test for calls to print(), str(), etc. Useful to make sure we don't forget
148238 # to add additional @properties to __repr__
@@ -161,6 +251,7 @@ def test_repr():
161251 num_frames_from_header: 390
162252 num_frames_from_content: 390
163253 average_fps_from_header: 29.97003
254+ pixel_aspect_ratio: 1
164255 duration_seconds: 13.013
165256 begin_stream_seconds: 0.0
166257 end_stream_seconds: 13.013
0 commit comments