From d4745bd08e01461c9f9b705e7b30af69661969cf Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Mon, 23 Sep 2024 05:45:58 -0400 Subject: [PATCH] Disallow setting frame.time_base with string --- av/utils.pxd | 2 +- av/utils.pyx | 12 +---------- tests/test_audioresampler.py | 40 +++++++++++++++++------------------- tests/test_codec_context.py | 2 +- tests/test_videoframe.py | 3 ++- 5 files changed, 24 insertions(+), 35 deletions(-) diff --git a/av/utils.pxd b/av/utils.pxd index 125272c5c..7f342c05b 100644 --- a/av/utils.pxd +++ b/av/utils.pxd @@ -7,7 +7,7 @@ cdef dict_to_avdict(lib.AVDictionary **dst, dict src, str encoding, str errors) cdef object avrational_to_fraction(const lib.AVRational *input) -cdef object to_avrational(object value, lib.AVRational *input) +cdef void to_avrational(object frac, lib.AVRational *input) cdef check_ndarray(object array, object dtype, int ndim) diff --git a/av/utils.pyx b/av/utils.pyx index cc01925de..afc82d24d 100644 --- a/av/utils.pyx +++ b/av/utils.pyx @@ -47,17 +47,7 @@ cdef object avrational_to_fraction(const lib.AVRational *input): return Fraction(input.num, input.den) -cdef object to_avrational(object value, lib.AVRational *input): - if value is None: - input.num = 0 - input.den = 1 - return - - if isinstance(value, Fraction): - frac = value - else: - frac = Fraction(value) - +cdef void to_avrational(object frac, lib.AVRational *input): input.num = frac.numerator input.den = frac.denominator diff --git a/tests/test_audioresampler.py b/tests/test_audioresampler.py index 58185f9d1..47dd1ddc3 100644 --- a/tests/test_audioresampler.py +++ b/tests/test_audioresampler.py @@ -1,12 +1,13 @@ from fractions import Fraction +import av from av import AudioFrame, AudioResampler from .common import TestCase class TestAudioResampler(TestCase): - def test_flush_immediately(self): + def test_flush_immediately(self) -> None: """ If we flush the resampler before passing any input, it returns a `None` frame without setting up the graph. @@ -18,7 +19,7 @@ def test_flush_immediately(self): oframes = resampler.resample(None) self.assertEqual(len(oframes), 0) - def test_identity_passthrough(self): + def test_identity_passthrough(self) -> None: """ If we don't ask it to do anything, it won't. """ @@ -37,13 +38,13 @@ def test_identity_passthrough(self): oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) - self.assertIs(iframe, oframes[0]) + assert iframe is oframes[0] # flush oframes = resampler.resample(None) self.assertEqual(len(oframes), 0) - def test_matching_passthrough(self): + def test_matching_passthrough(self) -> None: """ If the frames match, it won't do anything. """ @@ -68,9 +69,7 @@ def test_matching_passthrough(self): oframes = resampler.resample(None) self.assertEqual(len(oframes), 0) - def test_pts_assertion_same_rate(self): - import av - + def test_pts_assertion_same_rate(self) -> None: av.logging.set_level(av.logging.VERBOSE) resampler = AudioResampler("s16", "mono") @@ -117,13 +116,13 @@ def test_pts_assertion_same_rate(self): self.assertEqual(len(oframes), 0) av.logging.set_level(None) - def test_pts_assertion_new_rate_up(self): + def test_pts_assertion_new_rate_up(self) -> None: resampler = AudioResampler("s16", "mono", 44100) # resample one frame iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 48000 - iframe.time_base = "1/48000" + iframe.time_base = Fraction(1, 48000) iframe.pts = 0 oframes = resampler.resample(iframe) @@ -137,7 +136,7 @@ def test_pts_assertion_new_rate_up(self): iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 48000 - iframe.time_base = "1/48000" + iframe.time_base = Fraction(1, 48000) iframe.pts = 1024 oframes = resampler.resample(iframe) @@ -159,13 +158,13 @@ def test_pts_assertion_new_rate_up(self): self.assertEqual(oframe.sample_rate, 44100) self.assertEqual(oframe.samples, 15) - def test_pts_assertion_new_rate_down(self): + def test_pts_assertion_new_rate_down(self) -> None: resampler = AudioResampler("s16", "mono", 48000) # resample one frame iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 44100 - iframe.time_base = "1/44100" + iframe.time_base = Fraction(1, 44100) iframe.pts = 0 oframes = resampler.resample(iframe) @@ -179,7 +178,7 @@ def test_pts_assertion_new_rate_down(self): iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 44100 - iframe.time_base = "1/44100" + iframe.time_base = Fraction(1, 44100) iframe.pts = 1024 oframes = resampler.resample(iframe) @@ -201,13 +200,13 @@ def test_pts_assertion_new_rate_down(self): self.assertEqual(oframe.sample_rate, 48000) self.assertEqual(oframe.samples, 18) - def test_pts_assertion_new_rate_fltp(self): + def test_pts_assertion_new_rate_fltp(self) -> None: resampler = AudioResampler("fltp", "mono", 8000, 1024) # resample one frame iframe = AudioFrame("s16", "mono", 1024) iframe.sample_rate = 8000 - iframe.time_base = "1/1000" + iframe.time_base = Fraction(1, 1000) iframe.pts = 0 oframes = resampler.resample(iframe) @@ -221,7 +220,7 @@ def test_pts_assertion_new_rate_fltp(self): iframe = AudioFrame("s16", "mono", 1024) iframe.sample_rate = 8000 - iframe.time_base = "1/1000" + iframe.time_base = Fraction(1, 1000) iframe.pts = 8192 oframes = resampler.resample(iframe) @@ -237,7 +236,7 @@ def test_pts_assertion_new_rate_fltp(self): oframes = resampler.resample(None) self.assertEqual(len(oframes), 0) - def test_pts_missing_time_base(self): + def test_pts_missing_time_base(self) -> None: resampler = AudioResampler("s16", "mono", 44100) # resample one frame @@ -263,7 +262,7 @@ def test_pts_missing_time_base(self): self.assertEqual(oframe.sample_rate, 44100) self.assertEqual(oframe.samples, 16) - def test_mismatched_input(self): + def test_mismatched_input(self) -> None: """ Consecutive frames must have the same layout, sample format and sample rate. """ @@ -279,6 +278,5 @@ def test_mismatched_input(self): iframe.sample_rate = 48000 with self.assertRaises(ValueError) as cm: resampler.resample(iframe) - self.assertEqual( - str(cm.exception), "Frame does not match AudioResampler setup." - ) + + assert str(cm.exception) == "Frame does not match AudioResampler setup." diff --git a/tests/test_codec_context.py b/tests/test_codec_context.py index ad6247f2c..12997d76a 100644 --- a/tests/test_codec_context.py +++ b/tests/test_codec_context.py @@ -266,7 +266,7 @@ def test_encoding_dnxhd(self): "pix_fmt": "yuv422p", "width": 1920, "height": 1080, - "time_base": "1001/30000", + "time_base": Fraction(1001, 30_000), "max_frames": 5, } self.video_encoding("dnxhd", options) diff --git a/tests/test_videoframe.py b/tests/test_videoframe.py index 28540ccc3..9dff66d7f 100644 --- a/tests/test_videoframe.py +++ b/tests/test_videoframe.py @@ -1,3 +1,4 @@ +from fractions import Fraction from unittest import SkipTest import numpy @@ -595,7 +596,7 @@ class TestVideoFrameTiming(TestCase): def test_reformat_pts(self): frame = VideoFrame(640, 480, "rgb24") frame.pts = 123 - frame.time_base = "456/1" # Just to be different. + frame.time_base = Fraction("456/1") frame = frame.reformat(320, 240) self.assertEqual(frame.pts, 123) self.assertEqual(frame.time_base, 456)