Skip to content

Commit a790c52

Browse files
committed
Make container/streams pure
1 parent f9f80e6 commit a790c52

File tree

2 files changed

+60
-55
lines changed

2 files changed

+60
-55
lines changed

av/container/streams.pxd

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,7 @@ cimport libav as lib
22

33
from av.stream cimport Stream
44

5-
from .core cimport Container
6-
75

86
cdef class StreamContainer:
97
cdef list _streams
10-
11-
# For the different types.
12-
cdef readonly tuple video
13-
cdef readonly tuple audio
14-
cdef readonly tuple subtitles
15-
cdef readonly tuple attachments
16-
cdef readonly tuple data
17-
cdef readonly tuple other
18-
19-
cdef add_stream(self, Stream stream)
20-
cdef int _get_best_stream_index(self, Container container, lib.AVMediaType type_enum, Stream related) noexcept
21-
8+
cdef void add_stream(self, Stream stream)
Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
cimport libav as lib
1+
import cython
2+
import cython.cimports.libav as lib
3+
from cython.cimports.av.stream import Stream
24

35

46
def _flatten(input_):
@@ -9,7 +11,9 @@ def _flatten(input_):
911
else:
1012
yield x
1113

12-
cdef lib.AVMediaType _get_media_type_enum(str type):
14+
15+
@cython.cfunc
16+
def _get_media_type_enum(type: str) -> lib.AVMediaType:
1317
if type == "video":
1418
return lib.AVMEDIA_TYPE_VIDEO
1519
elif type == "audio":
@@ -23,7 +27,28 @@ def _flatten(input_):
2327
else:
2428
raise ValueError(f"Invalid stream type: {type}")
2529

26-
cdef class StreamContainer:
30+
31+
@cython.cfunc
32+
@cython.exceptval(check=False)
33+
def _get_best_stream_index(
34+
fmtctx: cython.pointer[lib.AVFormatContext],
35+
enumtype: lib.AVMediaType,
36+
related: Stream | None,
37+
) -> cython.int:
38+
stream_index: cython.int
39+
40+
if related is None:
41+
stream_index = lib.av_find_best_stream(fmtctx, enumtype, -1, -1, cython.NULL, 0)
42+
else:
43+
stream_index = lib.av_find_best_stream(
44+
fmtctx, enumtype, -1, related.ptr.index, cython.NULL, 0
45+
)
46+
47+
return stream_index
48+
49+
50+
@cython.cclass
51+
class StreamContainer:
2752
"""
2853
2954
A tuple-like container of :class:`Stream`.
@@ -40,31 +65,12 @@ def _flatten(input_):
4065

4166
def __cinit__(self):
4267
self._streams = []
43-
self.video = ()
44-
self.audio = ()
45-
self.subtitles = ()
46-
self.data = ()
47-
self.attachments = ()
48-
self.other = ()
49-
50-
cdef add_stream(self, Stream stream):
5168

69+
@cython.cfunc
70+
def add_stream(self, stream: Stream) -> cython.void:
5271
assert stream.ptr.index == len(self._streams)
5372
self._streams.append(stream)
5473

55-
if stream.ptr.codecpar.codec_type == lib.AVMEDIA_TYPE_VIDEO:
56-
self.video = self.video + (stream, )
57-
elif stream.ptr.codecpar.codec_type == lib.AVMEDIA_TYPE_AUDIO:
58-
self.audio = self.audio + (stream, )
59-
elif stream.ptr.codecpar.codec_type == lib.AVMEDIA_TYPE_SUBTITLE:
60-
self.subtitles = self.subtitles + (stream, )
61-
elif stream.ptr.codecpar.codec_type == lib.AVMEDIA_TYPE_ATTACHMENT:
62-
self.attachments = self.attachments + (stream, )
63-
elif stream.ptr.codecpar.codec_type == lib.AVMEDIA_TYPE_DATA:
64-
self.data = self.data + (stream, )
65-
else:
66-
self.other = self.other + (stream, )
67-
6874
# Basic tuple interface.
6975
def __len__(self):
7076
return len(self._streams)
@@ -78,6 +84,26 @@ def __getitem__(self, index):
7884
else:
7985
return self.get(index)
8086

87+
@property
88+
def video(self):
89+
return tuple(s for s in self._streams if s.type == "video")
90+
91+
@property
92+
def audio(self):
93+
return tuple(s for s in self._streams if s.type == "audio")
94+
95+
@property
96+
def subtitles(self):
97+
return tuple(s for s in self._streams if s.type == "subtitle")
98+
99+
@property
100+
def data(self):
101+
return tuple(s for s in self._streams if s.type == "data")
102+
103+
@property
104+
def attachments(self):
105+
return tuple(s for s in self._streams if s.type == "attachment")
106+
81107
def get(self, *args, **kwargs):
82108
"""get(streams=None, video=None, audio=None, subtitles=None, data=None)
83109
@@ -120,7 +146,9 @@ def get(self, *args, **kwargs):
120146

121147
elif isinstance(x, dict):
122148
for type_, indices in x.items():
123-
if type_ == "streams": # For compatibility with the pseudo signature
149+
if (
150+
type_ == "streams"
151+
): # For compatibility with the pseudo signature
124152
streams = self._streams
125153
else:
126154
streams = getattr(self, type_)
@@ -134,17 +162,7 @@ def get(self, *args, **kwargs):
134162

135163
return selection or self._streams[:]
136164

137-
cdef int _get_best_stream_index(self, Container container, lib.AVMediaType type_enum, Stream related) noexcept:
138-
cdef int stream_index
139-
140-
if related is None:
141-
stream_index = lib.av_find_best_stream(container.ptr, type_enum, -1, -1, NULL, 0)
142-
else:
143-
stream_index = lib.av_find_best_stream(container.ptr, type_enum, -1, related.ptr.index, NULL, 0)
144-
145-
return stream_index
146-
147-
def best(self, str type, /, Stream related = None):
165+
def best(self, type: str, /, related: Stream | None = None):
148166
"""best(type: Literal["video", "audio", "subtitle", "attachment", "data"], /, related: Stream | None)
149167
Finds the "best" stream in the file. Wraps :ffmpeg:`av_find_best_stream`. Example::
150168
@@ -155,14 +173,14 @@ def best(self, str type, /, Stream related = None):
155173
:return: The best stream of the specified type
156174
:rtype: Stream | None
157175
"""
158-
cdef type_enum = _get_media_type_enum(type)
159-
160176
if len(self._streams) == 0:
161177
return None
162178

163-
cdef container = self._streams[0].container
164-
165-
cdef int stream_index = self._get_best_stream_index(container, type_enum, related)
179+
first_stream: Stream = cython.cast(Stream, self._streams[0])
180+
container: cython.pointer[lib.AVFormatContext] = first_stream.container.ptr
181+
stream_index: cython.int = _get_best_stream_index(
182+
container, _get_media_type_enum(type), related
183+
)
166184

167185
if stream_index < 0:
168186
return None

0 commit comments

Comments
 (0)