Skip to content
Merged

Patch #2492

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Features:

- Add ``VideoFrame.solid()`` to create a frame filled with one color, in any non-paletted pixel format.
- Add ``Stream.cctx`` as the name for a stream's codec context; ``Stream.codec_context`` remains as an alias.
- Deprecate ``AudioStream.format``, ``AudioStream.layout``, and ``VideoStream.format``, which pass through to the codec context; use ``stream.cctx.format`` and ``stream.cctx.layout`` instead. Passing ``format`` or ``layout`` to ``add_stream()`` is not deprecated.
- Deprecate ``AudioStream.format``, ``AudioStream.layout``, ``VideoStream.format``, ``VideoStream.thread_count``, and ``VideoStream.thread_type``, which pass through to the codec context; use ``stream.cctx.format``, ``stream.cctx.layout``, ``stream.cctx.thread_count``, and ``stream.cctx.thread_type`` instead. Passing these to ``add_stream()`` is not deprecated.

Fixes:

Expand Down
6 changes: 3 additions & 3 deletions av/container/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ def _set_codecpar_extradata(

@cython.cfunc
def _set_stream_attrs(stream: Stream, ctx: CodecContext, kwargs: dict) -> cython.void:
# format and layout go straight to the codec context, since the stream
# passthroughs for them are deprecated.
# These go straight to the codec context, since the stream passthroughs
# for them are deprecated.
for k, v in kwargs.items():
if k == "format" or k == "layout":
if k in ("format", "layout", "thread_count", "thread_type"):
setattr(ctx, k, v)
else:
setattr(stream, k, v)
Expand Down
2 changes: 1 addition & 1 deletion av/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def __setattr__(self, name, value):
if name == "time_base":
to_avrational(value, cython.address(self.ptr.time_base))
return
if name == "format" or name == "layout":
if name in ("format", "layout", "thread_count", "thread_type"):
prop = getattr(type(self), name, None)
if prop is not None:
prop.__set__(self, value)
Expand Down
54 changes: 50 additions & 4 deletions av/video/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
from cython.cimports.libc.string import memcpy


def _warn_format_passthrough():
def _warn_passthrough(name):
warnings.warn(
"VideoStream.format is deprecated; use VideoStream.cctx.format instead",
f"VideoStream.{name} is deprecated; use VideoStream.cctx.{name} instead",
DeprecationWarning,
# Cython functions have no frames, so 1 is the caller.
stacklevel=1,
Expand Down Expand Up @@ -58,7 +58,7 @@ def format(self):

:type: VideoFormat | None
"""
_warn_format_passthrough()
_warn_passthrough("format")
if self.cctx is None:
raise AttributeError(
f"'{type(self).__name__}' object has no attribute 'format'"
Expand All @@ -67,10 +67,56 @@ def format(self):

@format.setter
def format(self, value):
_warn_format_passthrough()
_warn_passthrough("format")
if self.cctx is not None:
self.cctx.format = value

@property
def thread_count(self):
"""
The number of threads the codec context uses.

.. deprecated:: 19.1
Use ``stream.cctx.thread_count`` instead.

:type: int
"""
_warn_passthrough("thread_count")
if self.cctx is None:
raise AttributeError(
f"'{type(self).__name__}' object has no attribute 'thread_count'"
)
return self.cctx.thread_count

@thread_count.setter
def thread_count(self, value):
_warn_passthrough("thread_count")
if self.cctx is not None:
self.cctx.thread_count = value

@property
def thread_type(self):
"""
The threading type of the codec context.

.. deprecated:: 19.1
Use ``stream.cctx.thread_type`` instead.

:type: ThreadType
"""
_warn_passthrough("thread_type")
if self.cctx is None:
raise AttributeError(
f"'{type(self).__name__}' object has no attribute 'thread_type'"
)
return self.cctx.thread_type

@thread_type.setter
def thread_type(self, value):
_warn_passthrough("thread_type")
if self.cctx is not None:
self.cctx.thread_type = value

@cython.ccall
def encode(self, frame: VideoFrame | None = None):
"""
Expand Down
9 changes: 8 additions & 1 deletion av/video/stream.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,17 @@ class VideoStream(Stream):
@format.setter
@deprecated("Use VideoStream.cctx.format instead")
def format(self, value: VideoFormat) -> None: ...
thread_count: int
@property
@deprecated("Use VideoStream.cctx.thread_count instead")
def thread_count(self) -> int: ...
@thread_count.setter
@deprecated("Use VideoStream.cctx.thread_count instead")
def thread_count(self, value: int) -> None: ...
@property
@deprecated("Use VideoStream.cctx.thread_type instead")
def thread_type(self) -> ThreadType: ...
@thread_type.setter
@deprecated("Use VideoStream.cctx.thread_type instead")
def thread_type(self, value: int | str | ThreadType) -> None: ...
width: int
height: int
Expand Down
2 changes: 1 addition & 1 deletion examples/basics/hw_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

container = av.open(test_file_path)

container.streams.video[0].thread_type = "AUTO"
container.streams.video[0].cctx.thread_type = "AUTO"

start_time = time.time()
frame_count = 0
Expand Down
2 changes: 1 addition & 1 deletion examples/basics/thread_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
)

# !!! This is the only difference.
container.streams.video[0].thread_type = "AUTO"
container.streams.video[0].cctx.thread_type = "AUTO"

start_time = time.time()
for packet in container.demux():
Expand Down
2 changes: 1 addition & 1 deletion examples/numpy/barcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
container = av.open(
av.datasets.curated("pexels/time-lapse-video-of-sunset-by-the-sea-854400.mp4")
)
container.streams.video[0].thread_type = "AUTO" # Go faster!
container.streams.video[0].cctx.thread_type = "AUTO" # Go faster!

columns = []
for frame in container.decode(video=0):
Expand Down
46 changes: 39 additions & 7 deletions tests/test_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ def test_selection(self) -> None:
)
video = container.streams.video[0]

video.thread_type = av.codec.context.ThreadType.AUTO
assert video.thread_type == av.codec.context.ThreadType.AUTO
video.cctx.thread_type = av.codec.context.ThreadType.AUTO
assert video.cctx.thread_type == av.codec.context.ThreadType.AUTO

video.thread_type = 0x03
assert video.thread_type == av.codec.context.ThreadType.AUTO
video.cctx.thread_type = 0x03
assert video.cctx.thread_type == av.codec.context.ThreadType.AUTO

video.thread_type = "AUTO"
assert video.thread_type == av.codec.context.ThreadType.AUTO
video.cctx.thread_type = "AUTO"
assert video.cctx.thread_type == av.codec.context.ThreadType.AUTO

audio = container.streams.audio[0]

Expand Down Expand Up @@ -482,16 +482,48 @@ def test_video_format_passthrough_deprecated() -> None:
assert stream.format is not None


def test_video_thread_type_passthrough_deprecated() -> None:
with av.open(io.BytesIO(), "w", format="mp4") as output:
stream = output.add_stream("mpeg4", rate=24)
assert isinstance(stream, av.VideoStream)

with pytest.warns(DeprecationWarning, match=r"cctx\.thread_type"):
stream.thread_type = "AUTO"
assert stream.cctx.thread_type == av.codec.context.ThreadType.AUTO

with pytest.warns(DeprecationWarning, match=r"cctx\.thread_type"):
assert stream.thread_type == av.codec.context.ThreadType.AUTO


def test_video_thread_count_passthrough_deprecated() -> None:
with av.open(io.BytesIO(), "w", format="mp4") as output:
stream = output.add_stream("mpeg4", rate=24)
assert isinstance(stream, av.VideoStream)

with pytest.warns(DeprecationWarning, match=r"cctx\.thread_count"):
stream.thread_count = 2
assert stream.cctx.thread_count == 2

with pytest.warns(DeprecationWarning, match=r"cctx\.thread_count"):
assert stream.thread_count == 2


@pytest.mark.filterwarnings("error::DeprecationWarning")
def test_add_stream_format_layout_kwargs_not_deprecated() -> None:
with av.open(io.BytesIO(), "w", format="mp4") as output:
astream = output.add_stream("aac", rate=48000, format="fltp", layout="mono")
assert astream.cctx.layout.name == "mono"

vstream = output.add_stream(
"mpeg4", rate=24, format=av.VideoFormat("yuv420p", 32, 32)
"mpeg4",
rate=24,
format=av.VideoFormat("yuv420p", 32, 32),
thread_type="AUTO",
thread_count=2,
)
assert vstream.cctx.width == 32
assert vstream.cctx.thread_count == 2
assert vstream.cctx.thread_type == av.codec.context.ThreadType.AUTO

graph = av.filter.Graph()
graph.add_buffer(template=vstream, time_base=Fraction(1, 24))
Expand Down
Loading