forked from PyAV-Org/PyAV
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlayout.pyx
More file actions
125 lines (99 loc) · 3.92 KB
/
Copy pathlayout.pyx
File metadata and controls
125 lines (99 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from cpython cimport Py_INCREF, PyTuple_New, PyTuple_SET_ITEM
cimport libav as lib
cdef object _cinit_bypass_sentinel
cdef AudioLayout get_audio_layout(int channels, uint64_t c_layout):
"""Get an AudioLayout from Cython land."""
cdef AudioLayout layout = AudioLayout.__new__(AudioLayout, _cinit_bypass_sentinel)
if channels and not c_layout:
c_layout = default_layouts[channels]
layout._init(c_layout)
return layout
# These are the defaults given by FFmpeg; Libav is different.
cdef uint64_t default_layouts[9]
default_layouts[0] = 0
default_layouts[1] = lib.AV_CH_LAYOUT_MONO
default_layouts[2] = lib.AV_CH_LAYOUT_STEREO
default_layouts[3] = lib.AV_CH_LAYOUT_2POINT1
default_layouts[4] = lib.AV_CH_LAYOUT_4POINT0
default_layouts[5] = lib.AV_CH_LAYOUT_5POINT0_BACK
default_layouts[6] = lib.AV_CH_LAYOUT_5POINT1_BACK
default_layouts[7] = lib.AV_CH_LAYOUT_6POINT1
default_layouts[8] = lib.AV_CH_LAYOUT_7POINT1
# These are the descriptions as given by FFmpeg; Libav does not have them.
cdef dict channel_descriptions = {
'FL': 'front left',
'FR': 'front right',
'FC': 'front center',
'LFE': 'low frequency',
'BL': 'back left',
'BR': 'back right',
'FLC': 'front left-of-center',
'FRC': 'front right-of-center',
'BC': 'back center',
'SL': 'side left',
'SR': 'side right',
'TC': 'top center',
'TFL': 'top front left',
'TFC': 'top front center',
'TFR': 'top front right',
'TBL': 'top back left',
'TBC': 'top back center',
'TBR': 'top back right',
'DL': 'downmix left',
'DR': 'downmix right',
'WL': 'wide left',
'WR': 'wide right',
'SDL': 'surround direct left',
'SDR': 'surround direct right',
'LFE2': 'low frequency 2',
}
cdef class AudioLayout(object):
def __init__(self, layout):
if layout is _cinit_bypass_sentinel:
return
cdef uint64_t c_layout
if isinstance(layout, int):
if layout < 0 or layout > 8:
raise ValueError('no layout with %d channels' % layout)
c_layout = default_layouts[layout]
elif isinstance(layout, basestring):
c_layout = lib.av_get_channel_layout(layout)
else:
raise TypeError('layout must be str or int')
if not c_layout:
raise ValueError('invalid channel layout %r' % layout)
self._init(c_layout)
cdef _init(self, uint64_t layout):
self.layout = layout
self.nb_channels = lib.av_get_channel_layout_nb_channels(layout)
self.channels = PyTuple_New(self.nb_channels)
cdef AudioChannel c
for i in range(self.nb_channels):
# 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.
c = AudioChannel(self, i)
Py_INCREF(c)
PyTuple_SET_ITEM(self.channels, i, c)
def __repr__(self):
return '<av.%s %r>' % (self.__class__.__name__, self.name)
property name:
"""The canonical name of the audio layout."""
def __get__(self):
cdef char out[32]
# Passing 0 as number of channels... fix this later?
lib.av_get_channel_layout_string(out, 32, 0, self.layout)
return <str>out
cdef class AudioChannel(object):
def __cinit__(self, AudioLayout layout, int index):
self.channel = lib.av_channel_layout_extract_channel(layout.layout, index)
def __repr__(self):
return '<av.%s %r (%s)>' % (self.__class__.__name__, self.name, self.description)
property name:
"""The canonical name of the audio channel."""
def __get__(self):
return lib.av_get_channel_name(self.channel)
property description:
"""A human description of the audio channel."""
def __get__(self):
return channel_descriptions.get(self.name)