Skip to content

Commit

Permalink
Disallow setting frame.time_base with string
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Sep 23, 2024
1 parent 030632e commit d4745bd
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 35 deletions.
2 changes: 1 addition & 1 deletion av/utils.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 1 addition & 11 deletions av/utils.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
40 changes: 19 additions & 21 deletions tests/test_audioresampler.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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.
"""
Expand All @@ -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.
"""
Expand All @@ -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")

Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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.
"""
Expand All @@ -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."
2 changes: 1 addition & 1 deletion tests/test_codec_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_videoframe.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from fractions import Fraction
from unittest import SkipTest

import numpy
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit d4745bd

Please sign in to comment.