Skip to content

Commit 17b0b96

Browse files
committed
Add frame.rotation property
1 parent 1691b7c commit 17b0b96

File tree

7 files changed

+25
-41
lines changed

7 files changed

+25
-41
lines changed

av/sidedata/sidedata.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ cdef class SideData(Buffer):
1414

1515
cdef SideData wrap_side_data(Frame frame, int index)
1616

17+
cdef int get_display_rotation(Frame frame)
18+
1719
cdef class _SideDataContainer:
1820
cdef Frame frame
1921

av/sidedata/sidedata.pyx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from libc.stdint cimport int32_t
2+
13
from collections.abc import Mapping
24
from enum import Enum
35

@@ -45,13 +47,19 @@ class Type(Enum):
4547

4648

4749
cdef SideData wrap_side_data(Frame frame, int index):
48-
cdef lib.AVFrameSideDataType type_ = frame.ptr.side_data[index].type
49-
if type_ == lib.AV_FRAME_DATA_MOTION_VECTORS:
50+
if frame.ptr.side_data[index].type == lib.AV_FRAME_DATA_MOTION_VECTORS:
5051
return MotionVectors(_cinit_bypass_sentinel, frame, index)
5152
else:
5253
return SideData(_cinit_bypass_sentinel, frame, index)
5354

5455

56+
cdef int get_display_rotation(Frame frame):
57+
for i in range(frame.ptr.nb_side_data):
58+
if frame.ptr.side_data[i].type == lib.AV_FRAME_DATA_DISPLAYMATRIX:
59+
return int(lib.av_display_rotation_get(<const int32_t *>frame.ptr.side_data[i].data))
60+
return 0
61+
62+
5563
cdef class SideData(Buffer):
5664
def __init__(self, sentinel, Frame frame, int index):
5765
if sentinel is not _cinit_bypass_sentinel:

av/video/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
from . import display
21
from .frame import VideoFrame
32
from .stream import VideoStream

av/video/display.pyi

Lines changed: 0 additions & 16 deletions
This file was deleted.

av/video/display.pyx

Lines changed: 0 additions & 17 deletions
This file was deleted.

av/video/frame.pyx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ from enum import IntEnum
44
from libc.stdint cimport uint8_t
55

66
from av.error cimport err_check
7+
from av.sidedata.sidedata cimport get_display_rotation
78
from av.utils cimport check_ndarray
89
from av.video.format cimport get_pix_fmt, get_video_format
910
from av.video.plane cimport VideoPlane
@@ -172,6 +173,16 @@ cdef class VideoFrame(Frame):
172173
"""Height of the image, in pixels."""
173174
return self.ptr.height
174175

176+
@property
177+
def rotation(self):
178+
"""The rotation component of the `DISPLAYMATRIX` transformation matrix.
179+
180+
Returns:
181+
int: The angle (in degrees) by which the transformation rotates the frame
182+
counterclockwise. The angle will be in range [-180, 180].
183+
"""
184+
return get_display_rotation(self)
185+
175186
@property
176187
def interlaced_frame(self):
177188
"""Is this frame an interlaced or progressive?"""

tests/test_decode.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,9 @@ def test_flush_decoded_video_frame_count(self) -> None:
159159
def test_no_side_data(self):
160160
container = av.open(fate_suite("h264/interlaced_crop.mp4"))
161161
frame = next(container.decode(video=0))
162-
matrix = frame.side_data.get(av.sidedata.sidedata.Type.DISPLAYMATRIX)
163-
assert matrix is None
162+
assert frame.rotation == 0
164163

165164
def test_side_data(self):
166165
container = av.open(fate_suite("mov/displaymatrix.mov"))
167166
frame = next(container.decode(video=0))
168-
matrix = frame.side_data.get(av.sidedata.sidedata.Type.DISPLAYMATRIX)
169-
rotation = av.video.display.get_display_rotation(matrix)
170-
self.assertEqual(rotation, -90.0)
167+
assert frame.rotation == -90

0 commit comments

Comments
 (0)