forked from PyAV-Org/PyAV
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.pyx
More file actions
174 lines (121 loc) · 4.37 KB
/
Copy pathutils.pyx
File metadata and controls
174 lines (121 loc) · 4.37 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
from libc.stdint cimport int64_t, uint8_t, uint64_t
from fractions import Fraction
from threading import local
import sys
import traceback
cimport libav as lib
from av.logging cimport _get_last_error
# === ERROR HANDLING ===
# ======================
# Would love to use the built-in constant, but it doesn't appear to
# exist on Travis, or my Linux workstation. Could this be because they
# are actually libav?
cdef int AV_ERROR_MAX_STRING_SIZE = 64
# Our custom error.
cdef int PYAV_ERROR = -0x50794156 # 'PyAV'
class AVError(EnvironmentError):
"""Exception class for errors from within the underlying FFmpeg/Libav."""
def __init__(self, code, message, filename=None, error_log=None):
if filename:
super(AVError, self).__init__(code, message, filename)
else:
super(AVError, self).__init__(code, message)
self.error_log = error_log
if error_log:
self.strerror = '%s (%s: %s)' % (self.strerror, error_log[0], error_log[1])
AVError.__module__ = 'av'
cdef object _local = local()
cdef int _err_count = 0
cdef int stash_exception(exc_info=None):
global _err_count
existing = getattr(_local, 'exc_info', None)
if existing is not None:
print >> sys.stderr, 'PyAV library exception being dropped:'
traceback.print_exception(*existing)
_err_count -= 1
exc_info = exc_info or sys.exc_info()
_local.exc_info = exc_info
if exc_info:
_err_count += 1
return PYAV_ERROR
cdef int _last_log_count = 0
cdef int err_check(int res=0, str filename=None) except -1:
global _err_count
global _last_log_count
# Check for stashed exceptions.
if _err_count:
exc_info = getattr(_local, 'exc_info', None)
if exc_info is not None:
_err_count -= 1
_local.exc_info = None
raise exc_info[0], exc_info[1], exc_info[2]
if res >= 0:
return res
cdef bytes py_buffer
cdef char *c_buffer
if res == PYAV_ERROR:
py_buffer = b'Error in PyAV callback'
else:
# This is kinda gross.
py_buffer = b"\0" * AV_ERROR_MAX_STRING_SIZE
c_buffer = py_buffer
lib.av_strerror(res, c_buffer, AV_ERROR_MAX_STRING_SIZE)
py_buffer = c_buffer
cdef unicode message = py_buffer.decode('latin1')
# Add details from the last log onto the end.
error_log = None
log_count, last_log = _get_last_error()
if log_count > _last_log_count:
error_log = (last_log[0].strip(), last_log[2].strip())
_last_log_count = log_count
if filename:
raise AVError(-res, message, filename, error_log)
else:
raise AVError(-res, message, None, error_log)
return res
# === DICTIONARIES ===
# ====================
cdef dict avdict_to_dict(lib.AVDictionary *input):
cdef lib.AVDictionaryEntry *element = NULL
cdef dict output = {}
while True:
element = lib.av_dict_get(input, "", element, lib.AV_DICT_IGNORE_SUFFIX)
if element == NULL:
break
output[element.key] = element.value
return output
cdef dict_to_avdict(lib.AVDictionary **dst, dict src, bint clear=True):
if clear:
lib.av_dict_free(dst)
for key, value in src.iteritems():
err_check(lib.av_dict_set(dst, key, value, 0))
# === FRACTIONS ===
# =================
cdef object avrational_to_faction(lib.AVRational *input):
return Fraction(input.num, input.den) if input.den else Fraction(0, 1)
cdef object to_avrational(object value, lib.AVRational *input):
if isinstance(value, Fraction):
frac = value
else:
frac = Fraction(value)
input.num = frac.numerator
input.den = frac.denominator
cdef object av_frac_to_fraction(lib.AVFrac *input):
return Fraction(input.val * input.num, input.den)
# === OTHER ===
# =============
cdef str media_type_to_string(lib.AVMediaType media_type):
# There is a convenient lib.av_get_media_type_string(x), but it
# doesn't exist in libav.
if media_type == lib.AVMEDIA_TYPE_VIDEO:
return "video"
elif media_type == lib.AVMEDIA_TYPE_AUDIO:
return "audio"
elif media_type == lib.AVMEDIA_TYPE_DATA:
return "data"
elif media_type == lib.AVMEDIA_TYPE_SUBTITLE:
return "subtitle"
elif media_type == lib.AVMEDIA_TYPE_ATTACHMENT:
return "attachment"
else:
return "unknown"