diff --git a/av/audio/frame.pyx b/av/audio/frame.pyx index d4647ed49..61ce4b76d 100644 --- a/av/audio/frame.pyx +++ b/av/audio/frame.pyx @@ -81,15 +81,12 @@ cdef class AudioFrame(Frame): align )) - self._init_planes(AudioPlane) - def __dealloc__(self): lib.av_freep(&self._buffer) cdef _init_user_attributes(self): self.layout = get_audio_layout(0, self.ptr.channel_layout) self.format = get_audio_format(self.ptr.format) - self._init_planes(AudioPlane) def __repr__(self): return '' % ( @@ -131,6 +128,19 @@ cdef class AudioFrame(Frame): plane.update(array[i, :]) return frame + @property + def planes(self): + """ + A tuple of :class:`~av.audio.plane.AudioPlane`. + + :type: tuple + """ + cdef int plane_count = 0 + while self.ptr.extended_data[plane_count]: + plane_count += 1 + + return tuple([AudioPlane(self, i) for i in range(plane_count)]) + property samples: """ Number of audio samples (per channel). diff --git a/av/frame.pxd b/av/frame.pxd index bd42d360a..e63c72ebf 100644 --- a/av/frame.pxd +++ b/av/frame.pxd @@ -13,16 +13,6 @@ cdef class Frame(object): cdef readonly int index - cdef readonly tuple planes - """ - A tuple of :class:`~av.audio.plane.AudioPlane` or :class:`~av.video.plane.VideoPlane` objects. - - :type: tuple - """ - - cdef _init_planes(self, cls=?) - cdef int _max_plane_count(self) - cdef _copy_internal_attributes(self, Frame source, bint data_layout=?) cdef _init_user_attributes(self) diff --git a/av/frame.pyx b/av/frame.pyx index ec75a5570..25214341c 100644 --- a/av/frame.pyx +++ b/av/frame.pyx @@ -1,8 +1,3 @@ -from libc.limits cimport INT_MAX - -from cpython cimport Py_INCREF, PyTuple_New, PyTuple_SET_ITEM - -from av.plane cimport Plane from av.utils cimport avrational_to_fraction, to_avrational from fractions import Fraction @@ -33,29 +28,6 @@ cdef class Frame(object): self.pts, ) - cdef _init_planes(self, cls=Plane): - - # We need to detect which planes actually exist, but also contrain - # ourselves to the maximum plane count (as determined only by VideoFrames - # so far), in case the library implementation does not set the last - # plane to NULL. - cdef int max_plane_count = self._max_plane_count() - cdef int plane_count = 0 - while plane_count < max_plane_count and self.ptr.extended_data[plane_count]: - plane_count += 1 - - self.planes = PyTuple_New(plane_count) - for i in range(plane_count): - # We are constructing this tuple manually, but since Cython does - # not understand reference stealing we must manually Py_INCREF - # so that when Cython Py_DECREFs it doesn't release our object. - plane = cls(self, i) - Py_INCREF(plane) - PyTuple_SET_ITEM(self.planes, i, plane) - - cdef int _max_plane_count(self): - return INT_MAX - cdef _copy_internal_attributes(self, Frame source, bint data_layout=True): """Mimic another frame.""" self.index = source.index diff --git a/av/video/frame.pyx b/av/video/frame.pyx index 50257e9c5..7c114c0ca 100644 --- a/av/video/frame.pyx +++ b/av/video/frame.pyx @@ -106,12 +106,8 @@ cdef class VideoFrame(Frame): self._init_user_attributes() - cdef int _max_plane_count(self): - return self.format.ptr.nb_components - cdef _init_user_attributes(self): self.format = get_video_format(self.ptr.format, self.ptr.width, self.ptr.height) - self._init_planes(VideoPlane) def __dealloc__(self): # The `self._buffer` member is only set if *we* allocated the buffer in `_init`, @@ -274,6 +270,24 @@ cdef class VideoFrame(Frame): return frame + @property + def planes(self): + """ + A tuple of :class:`~av.video.plane.VideoPlane` objects. + + :type: tuple + """ + # We need to detect which planes actually exist, but also contrain + # ourselves to the maximum plane count (as determined only by VideoFrames + # so far), in case the library implementation does not set the last + # plane to NULL. + cdef int max_plane_count = self.format.ptr.nb_components + cdef int plane_count = 0 + while plane_count < max_plane_count and self.ptr.extended_data[plane_count]: + plane_count += 1 + + return tuple([VideoPlane(self, i) for i in range(plane_count)]) + property width: """Width of the image, in pixels.""" def __get__(self): return self.ptr.width