Skip to content

Commit 11142a4

Browse files
hyenalSebastien EhrhardtWyattBlue
authored
Expose DISPLAYMATRIX side data
Co-authored-by: Sebastien Ehrhardt <sebastien.ehrhardt@onfido.com> Co-authored-by: WyattBlue <wyattblue@auto-editor.com>
1 parent c8b535a commit 11142a4

File tree

6 files changed

+93
-1
lines changed

6 files changed

+93
-1
lines changed

av/stream.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ cdef class Stream:
1212
# Stream attributes.
1313
cdef readonly Container container
1414
cdef readonly dict metadata
15+
cdef readonly int nb_side_data
16+
cdef readonly dict side_data
1517

1618
# CodecContext attributes.
1719
cdef readonly CodecContext codec_context
1820

1921
# Private API.
2022
cdef _init(self, Container, lib.AVStream*, CodecContext)
2123
cdef _finalize_for_output(self)
24+
cdef _get_side_data(self, lib.AVStream *stream)
2225
cdef _set_time_base(self, value)
2326
cdef _set_id(self, value)
2427

av/stream.pyx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import warnings
22

3+
from libc.stdint cimport int32_t
34
cimport libav as lib
45

6+
from av.enum cimport define_enum
57
from av.error cimport err_check
68
from av.packet cimport Packet
79
from av.utils cimport (
@@ -17,6 +19,12 @@ from av.deprecation import AVDeprecationWarning
1719
cdef object _cinit_bypass_sentinel = object()
1820

1921

22+
# If necessary more can be added from
23+
# https://ffmpeg.org/doxygen/trunk/group__lavc__packet.html#ga9a80bfcacc586b483a973272800edb97
24+
SideData = define_enum("SideData", __name__, (
25+
("DISPLAYMATRIX", lib.AV_PKT_DATA_DISPLAYMATRIX, "Display Matrix"),
26+
))
27+
2028
cdef Stream wrap_stream(Container container, lib.AVStream *c_stream, CodecContext codec_context):
2129
"""Build an av.Stream for an existing AVStream.
2230
@@ -79,6 +87,8 @@ cdef class Stream:
7987
if self.codec_context:
8088
self.codec_context.stream_index = stream.index
8189

90+
self.nb_side_data, self.side_data = self._get_side_data(stream)
91+
8292
self.metadata = avdict_to_dict(
8393
stream.metadata,
8494
encoding=self.container.metadata_encoding,
@@ -103,6 +113,11 @@ cdef class Stream:
103113
AVDeprecationWarning
104114
)
105115

116+
if name == "side_data":
117+
return self.side_data
118+
elif name == "nb_side_data":
119+
return self.nb_side_data
120+
106121
# Convenience getter for codec context properties.
107122
if self.codec_context is not None:
108123
return getattr(self.codec_context, name)
@@ -167,6 +182,20 @@ cdef class Stream:
167182

168183
return self.codec_context.decode(packet)
169184

185+
cdef _get_side_data(self, lib.AVStream *stream):
186+
# Get DISPLAYMATRIX SideDate from a lib.AVStream object.
187+
# Returns: tuple[int, dict[str, Any]]
188+
189+
nb_side_data = stream.nb_side_data
190+
side_data = {}
191+
192+
for i in range(nb_side_data):
193+
# Based on: https://www.ffmpeg.org/doxygen/trunk/dump_8c_source.html#l00430
194+
if stream.side_data[i].type == lib.AV_PKT_DATA_DISPLAYMATRIX:
195+
side_data["DISPLAYMATRIX"] = lib.av_display_rotation_get(<const int32_t *>stream.side_data[i].data)
196+
197+
return nb_side_data, side_data
198+
170199
property id:
171200
"""
172201
The format-specific ID of this stream.

include/libavcodec/avcodec.pxd

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,46 @@ cdef extern from "libavcodec/avcodec.h" nogil:
258258

259259
cdef int AV_NUM_DATA_POINTERS
260260

261+
cdef enum AVPacketSideDataType:
262+
AV_PKT_DATA_PALETTE
263+
AV_PKT_DATA_NEW_EXTRADATA
264+
AV_PKT_DATA_PARAM_CHANGE
265+
AV_PKT_DATA_H263_MB_INFO
266+
AV_PKT_DATA_REPLAYGAIN
267+
AV_PKT_DATA_DISPLAYMATRIX
268+
AV_PKT_DATA_STEREO3D
269+
AV_PKT_DATA_AUDIO_SERVICE_TYPE
270+
AV_PKT_DATA_QUALITY_STATS
271+
AV_PKT_DATA_FALLBACK_TRACK
272+
AV_PKT_DATA_CPB_PROPERTIES
273+
AV_PKT_DATA_SKIP_SAMPLES
274+
AV_PKT_DATA_JP_DUALMONO
275+
AV_PKT_DATA_STRINGS_METADATA
276+
AV_PKT_DATA_SUBTITLE_POSITION
277+
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL
278+
AV_PKT_DATA_WEBVTT_IDENTIFIER
279+
AV_PKT_DATA_WEBVTT_SETTINGS
280+
AV_PKT_DATA_METADATA_UPDATE
281+
AV_PKT_DATA_MPEGTS_STREAM_ID
282+
AV_PKT_DATA_MASTERING_DISPLAY_METADATA
283+
AV_PKT_DATA_SPHERICAL
284+
AV_PKT_DATA_CONTENT_LIGHT_LEVEL
285+
AV_PKT_DATA_A53_CC
286+
AV_PKT_DATA_ENCRYPTION_INIT_INFO
287+
AV_PKT_DATA_ENCRYPTION_INFO
288+
AV_PKT_DATA_AFD
289+
AV_PKT_DATA_PRFT
290+
AV_PKT_DATA_ICC_PROFILE
291+
AV_PKT_DATA_DOVI_CONF
292+
AV_PKT_DATA_S12M_TIMECODE
293+
AV_PKT_DATA_DYNAMIC_HDR10_PLUS
294+
AV_PKT_DATA_NB
295+
296+
cdef struct AVPacketSideData:
297+
uint8_t *data;
298+
size_t size;
299+
AVPacketSideDataType type;
300+
261301
cdef enum AVFrameSideDataType:
262302
AV_FRAME_DATA_PANSCAN
263303
AV_FRAME_DATA_A53_CC

include/libavformat/avformat.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ cdef extern from "libavformat/avformat.h" nogil:
4747
AVRational r_frame_rate
4848
AVRational sample_aspect_ratio
4949

50+
int nb_side_data
51+
AVPacketSideData *side_data
52+
53+
5054
# http://ffmpeg.org/doxygen/trunk/structAVIOContext.html
5155
cdef struct AVIOContext:
5256
unsigned char* buffer

include/libavutil/avutil.pxd

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
from libc.stdint cimport int64_t, uint8_t, uint64_t
1+
from libc.stdint cimport int64_t, uint8_t, uint64_t, int32_t
22

33

44
cdef extern from "libavutil/mathematics.h" nogil:
55
pass
66

7+
cdef extern from "libavutil/display.h" nogil:
8+
cdef double av_display_rotation_get(const int32_t matrix[9])
9+
710
cdef extern from "libavutil/rational.h" nogil:
811
cdef int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
912

tests/test_streams.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,16 @@ def test_selection(self):
2424
self.assertEqual([video], container.streams.get(video=(0,)))
2525

2626
# TODO: Find something in the fate suite with video, audio, and subtitles.
27+
28+
def test_noside_data(self):
29+
container = av.open(fate_suite("h264/interlaced_crop.mp4"))
30+
video = container.streams.video[0]
31+
32+
self.assertEqual(video.nb_side_data, 0)
33+
34+
def test_side_data(self):
35+
container = av.open(fate_suite("mov/displaymatrix.mov"))
36+
video = container.streams.video[0]
37+
38+
self.assertEqual(video.nb_side_data, 1)
39+
self.assertEqual(video.side_data["DISPLAYMATRIX"], -90.0)

0 commit comments

Comments
 (0)