Skip to content
Merged
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
7 changes: 5 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ We are operating with `semantic versioning <https://semver.org>`_.
- $CHANGE by :gh-user:`mikeboers` in (:pr:`1`).


v19.0.1
-------
v19.0.1 (Unreleased)
--------------------

Fixes:

- Reading :attr:`.Frame.side_data` no longer holds the frame in a reference cycle, which kept its picture buffer alive until gc ran. By :gh-user:`WyattBlue`.
- :class:`.MotionVectors` no longer memoizes the vectors it hands out, a cache that never evicted and put every one of them in a reference cycle with the side data, retaining 1640 objects for a single 640x360 frame. By :gh-user:`WyattBlue`.
- :attr:`.Stream.index_entries` is now a view built on access rather than an object allocated for every stream whether or not anything reads it, which also takes the stream out of a reference cycle with it. Fixes (:issue:`2425`) by :gh-user:`WyattBlue`.


v19.0.0
Expand Down
2 changes: 0 additions & 2 deletions av/frame.pxd
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
cimport libav as lib

from av.packet cimport Packet
from av.sidedata.sidedata cimport _SideDataContainer


cdef class Frame:
cdef lib.AVFrame *ptr
# We define our own time.
cdef lib.AVRational _time_base
cdef void _rebase_time(self, lib.AVRational)
cdef _SideDataContainer _side_data
cdef void _copy_internal_attributes(self, Frame source, bint data_layout=?)
cdef void _init_user_attributes(self)
4 changes: 1 addition & 3 deletions av/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,7 @@ def key_frame(self, v):

@property
def side_data(self):
if self._side_data is None:
self._side_data = SideDataContainer(self)
return self._side_data
return SideDataContainer(self)

@property
def metadata(self):
Expand Down
3 changes: 2 additions & 1 deletion av/frame.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class Frame:
def time_base(self) -> AVRational: ...
@time_base.setter
def time_base(self, value: AVRational | Fraction | int) -> None: ...
side_data: SideDataContainer
@property
def side_data(self) -> SideDataContainer: ...
opaque: object
@property
def metadata(self) -> dict[str, str]: ...
Expand Down
1 change: 0 additions & 1 deletion av/sidedata/motionvectors.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ from av.sidedata.sidedata cimport SideData


cdef class MotionVectors(SideData):
cdef dict _vectors
cdef Py_ssize_t _len


Expand Down
11 changes: 1 addition & 10 deletions av/sidedata/motionvectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
class MotionVectors(SideData):
def __init__(self, sentinel, frame: Frame, index: cython.int):
SideData.__init__(self, sentinel, frame, index)
self._vectors = {}
self._len = self.ptr.size // cython.sizeof(lib.AVMotionVector)

def __repr__(self):
Expand All @@ -29,15 +28,7 @@ def __getitem__(self, index: cython.Py_ssize_t):
if index < 0 or index >= self._len:
raise IndexError(index)

try:
return self._vectors[index]
except KeyError:
pass

vector = self._vectors[index] = MotionVector(
_cinit_bypass_sentinel, self, index
)
return vector
return MotionVector(_cinit_bypass_sentinel, self, index)

def __iter__(self):
"""Iterate over all motion vectors."""
Expand Down
7 changes: 3 additions & 4 deletions av/sidedata/motionvectors.pyi
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from typing import Any, overload
from collections.abc import Iterator
from typing import Any

import numpy as np

from .sidedata import SideData

class MotionVectors(SideData):
@overload
def __getitem__(self, index: int) -> MotionVector: ...
@overload
def __getitem__(self, index: slice) -> list[MotionVector]: ...
def __iter__(self) -> Iterator[MotionVector]: ...
def __len__(self) -> int: ...
def to_ndarray(self) -> np.ndarray[Any, Any]: ...

Expand Down
2 changes: 0 additions & 2 deletions av/sidedata/sidedata.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ from enum import Enum
from typing import ClassVar, cast, overload

from av.buffer import Buffer
from av.frame import Frame

class Type(Enum):
PANSCAN = cast(ClassVar[Type], ...)
Expand Down Expand Up @@ -43,7 +42,6 @@ class SideData(Buffer):
type: Type

class SideDataContainer(Mapping):
frame: Frame
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[Type]: ...
@overload
Expand Down
Loading