1# ----------------------------------------------------------------------------
2# pyglet
3# Copyright (c) 2006-2008 Alex Holkner
4# Copyright (c) 2008-2020 pyglet contributors
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11#  * Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13#  * Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in
15#    the documentation and/or other materials provided with the
16#    distribution.
17#  * Neither the name of pyglet nor the names of its
18#    contributors may be used to endorse or promote products
19#    derived from this software without specific prior written
20#    permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33# POSSIBILITY OF SUCH DAMAGE.
34# ----------------------------------------------------------------------------
35"""Wrapper for include/libavformat/avformat.h
36"""
37from ctypes import c_int, c_uint16, c_int32, c_int64, c_uint32, c_uint64
38from ctypes import c_uint8, c_uint, c_double, c_float, c_ubyte, c_size_t, c_char, c_char_p
39from ctypes import c_void_p, addressof, byref, cast, POINTER, CFUNCTYPE, Structure, Union
40from ctypes import create_string_buffer, memmove
41
42import pyglet
43import pyglet.lib
44from . import libavcodec
45from . import libavutil
46
47avformat = pyglet.lib.load_library(
48    'avformat',
49    win32='avformat-58',
50    darwin='avformat.58'
51)
52
53AVSEEK_FLAG_BACKWARD = 1  # ///< seek backward
54AVSEEK_FLAG_BYTE = 2  # ///< seeking based on position in bytes
55AVSEEK_FLAG_ANY = 4  # ///< seek to any frame, even non-keyframes
56AVSEEK_FLAG_FRAME = 8  # ///< seeking based on frame number
57
58MAX_REORDER_DELAY = 16
59
60
61class AVPacketList(Structure): pass
62
63
64class AVInputFormat(Structure):
65    _fields_ = [
66        ('name', c_char_p)
67    ]
68
69
70class AVOutputFormat(Structure):
71    pass
72
73
74class AVIOContext(Structure):
75    pass
76
77
78class AVIndexEntry(Structure):
79    pass
80
81
82class AVStreamInfo(Structure):
83    _fields_ = [
84        ('last_dts', c_int64),
85        ('duration_gcd', c_int64),
86        ('duration_count', c_int),
87        ('rfps_duration_sum', c_int64),
88        ('duration_error', POINTER(c_double * 2 * (30 * 12 + 30 + 3 + 6))),
89        ('codec_info_duration', c_int64),
90        ('codec_info_duration_fields', c_int64),
91        ('frame_delay_evidence', c_int),
92        ('found_decoder', c_int),
93        ('last_duration', c_int64),
94        ('fps_first_dts', c_int64),
95        ('fps_first_dts_idx', c_int),
96        ('fps_last_dts', c_int64),
97        ('fps_last_dts_idx', c_int),
98    ]
99
100
101class AVProbeData(Structure):
102    _fields_ = [
103        ('filename', c_char_p),
104        ('buf', POINTER(c_ubyte)),
105        ('buf_size', c_int),
106        ('mime_type', c_char_p)
107    ]
108
109
110class FFFrac(Structure):
111    pass
112
113
114class AVStreamInternal(Structure):
115    pass
116
117
118class AVFrac(Structure):
119    _fields_ = [
120        ('val', c_int64),
121        ('num', c_int64),
122        ('den', c_int64),
123    ]
124
125
126AVCodecContext = libavcodec.AVCodecContext
127AVPacketSideData = libavcodec.AVPacketSideData
128AVPacket = libavcodec.AVPacket
129AVCodecParserContext = libavcodec.AVCodecParserContext
130AVCodecParameters = libavcodec.AVCodecParameters
131AVRational = libavutil.AVRational
132AVDictionary = libavutil.AVDictionary
133AVFrame = libavutil.AVFrame
134
135
136class AVStream(Structure):
137    _fields_ = [
138        ('index', c_int),
139        ('id', c_int),
140        ('codec', POINTER(AVCodecContext)),
141        ('priv_data', c_void_p),
142        ('time_base', AVRational),
143        ('start_time', c_int64),
144        ('duration', c_int64),
145        ('nb_frames', c_int64),
146        ('disposition', c_int),
147        ('discard', c_int),
148        ('sample_aspect_ratio', AVRational),
149        ('metadata', POINTER(AVDictionary)),
150        ('avg_frame_rate', AVRational),
151        ('attached_pic', AVPacket),
152        ('side_data', POINTER(AVPacketSideData)),
153        ('nb_side_data', c_int),
154        ('event_flags', c_int),
155        ('r_frame_rate', AVRational),
156        ('recommended_encoder_configuration', c_char_p),
157        ('codecpar', POINTER(AVCodecParameters)),
158        ('info', POINTER(AVStreamInfo)),
159        ('pts_wrap_bits', c_int),
160        ('first_dts', c_int64),
161        ('cur_dts', c_int64),
162        ('last_IP_pts', c_int64),
163        ('last_IP_duration', c_int),
164        ('probe_packets', c_int),
165        ('codec_info_nb_frames', c_int),
166        ('need_parsing', c_int),
167        ('parser', POINTER(AVCodecParserContext)),
168        ('last_in_packet_buffer', POINTER(AVPacketList)),
169        ('probe_data', AVProbeData),
170        ('pts_buffer', c_int64 * (MAX_REORDER_DELAY + 1)),
171        ('index_entries', POINTER(AVIndexEntry)),
172        ('nb_index_entries', c_int),
173        ('index_entries_allocated_size', c_uint),
174        ('stream_identifier', c_int),
175        ('interleaver_chunk_size', c_int64),
176        ('interleaver_chunk_duration', c_int64),
177        ('request_probe', c_int),
178        ('skip_to_keyframe', c_int),
179        ('skip_samples', c_int),
180        ('start_skip_samples', c_int64),
181        ('first_discard_sample', c_int64),
182        ('last_discard_sample', c_int64),
183        ('nb_decoded_frames', c_int),
184        ('mux_ts_offset', c_int64),
185        ('pts_wrap_reference', c_int64),
186        ('pts_wrap_behavior', c_int),
187        ('update_initial_durations_done', c_int),
188        ('pts_reorder_error', c_int64 * (MAX_REORDER_DELAY + 1)),
189        ('pts_reorder_error_count', c_uint8 * (MAX_REORDER_DELAY + 1)),
190        ('last_dts_for_order_check', c_int64),
191        ('dts_ordered', c_uint8),
192        ('dts_misordered', c_uint8),
193        ('inject_global_side_data', c_int),
194        ('display_aspect_ratio', AVRational),
195        ('internal', POINTER(AVStreamInternal))
196    ]
197
198
199class AVProgram(Structure):
200    pass
201
202
203class AVChapter(Structure):
204    pass
205
206
207class AVFormatInternal(Structure):
208    pass
209
210
211class AVIOInterruptCB(Structure):
212    _fields_ = [
213        ('callback', CFUNCTYPE(c_int, c_void_p)),
214        ('opaque', c_void_p)
215    ]
216
217
218AVClass = libavutil.AVClass
219AVCodec = libavcodec.AVCodec
220
221
222class AVFormatContext(Structure):
223    pass
224
225
226AVFormatContext._fields_ = [
227    ('av_class', POINTER(AVClass)),
228    ('iformat', POINTER(AVInputFormat)),
229    ('oformat', POINTER(AVOutputFormat)),
230    ('priv_data', c_void_p),
231    ('pb', POINTER(AVIOContext)),
232    ('ctx_flags', c_int),
233    ('nb_streams', c_uint),
234    ('streams', POINTER(POINTER(AVStream))),
235    ('filename', c_char * 1024),  # Deprecated
236    ('url', c_char_p),
237    ('start_time', c_int64),
238    ('duration', c_int64),
239    ('bit_rate', c_int64),
240    ('packet_size', c_uint),
241    ('max_delay', c_int),
242    ('flags', c_int),
243    ('probesize', c_int64),
244    ('max_analyze_duration', c_int64),
245    ('key', POINTER(c_uint8)),
246    ('keylen', c_int),
247    ('nb_programs', c_uint),
248    ('programs', POINTER(POINTER(AVProgram))),
249    ('video_codec_id', c_int),
250    ('audio_codec_id', c_int),
251    ('subtitle_codec_id', c_int),
252    ('max_index_size', c_uint),
253    ('max_picture_buffer', c_uint),
254    ('nb_chapters', c_uint),
255    ('chapters', POINTER(POINTER(AVChapter))),
256    ('metadata', POINTER(AVDictionary)),
257    ('start_time_realtime', c_int64),
258    ('fps_probe_size', c_int),
259    ('error_recognition', c_int),
260    ('interrupt_callback', AVIOInterruptCB),
261    ('debug', c_int),
262    ('max_interleave_delta', c_int64),
263    ('strict_std_compliance', c_int),
264    ('event_flags', c_int),
265    ('max_ts_probe', c_int),
266    ('avoid_negative_ts', c_int),
267    ('ts_id', c_int),
268    ('audio_preload', c_int),
269    ('max_chunk_duration', c_int),
270    ('max_chunk_size', c_int),
271    ('use_wallclock_as_timestamps', c_int),
272    ('avio_flags', c_int),
273    ('duration_estimation_method', c_uint),
274    ('skip_initial_bytes', c_int64),
275    ('correct_ts_overflow', c_uint),
276    ('seek2any', c_int),
277    ('flush_packets', c_int),
278    ('probe_score', c_int),
279    ('format_probesize', c_int),
280    ('codec_whitelist', c_char_p),
281    ('format_whitelist', c_char_p),
282    ('internal', POINTER(AVFormatInternal)),
283    ('io_repositioned', c_int),
284    ('video_codec', POINTER(AVCodec)),
285    ('audio_codec', POINTER(AVCodec)),
286    ('subtitle_codec', POINTER(AVCodec)),
287    ('data_codec', POINTER(AVCodec)),
288    ('metadata_header_padding', c_int),
289    ('opaque', c_void_p),
290    ('control_message_cb', CFUNCTYPE(c_int,
291                                     POINTER(AVFormatContext), c_int, c_void_p,
292                                     c_size_t)),
293    ('output_ts_offset', c_int64),
294    ('dump_separator', POINTER(c_uint8)),
295    ('data_codec_id', c_int),
296    # ! one more in here?
297    ('protocol_whitelist', c_char_p),
298    ('io_open', CFUNCTYPE(c_int,
299                          POINTER(AVFormatContext),
300                          POINTER(POINTER(AVIOContext)),
301                          c_char_p, c_int,
302                          POINTER(POINTER(AVDictionary)))),
303    ('io_close', CFUNCTYPE(None,
304                           POINTER(AVFormatContext), POINTER(AVIOContext))),
305    ('protocol_blacklist', c_char_p),
306    ('max_streams', c_int)
307]
308
309avformat.av_register_all.restype = None
310avformat.av_find_input_format.restype = c_int
311avformat.av_find_input_format.argtypes = [c_int]
312avformat.avformat_open_input.restype = c_int
313avformat.avformat_open_input.argtypes = [
314    POINTER(POINTER(AVFormatContext)),
315    c_char_p,
316    POINTER(AVInputFormat),
317    POINTER(POINTER(AVDictionary))]
318avformat.avformat_find_stream_info.restype = c_int
319avformat.avformat_find_stream_info.argtypes = [
320    POINTER(AVFormatContext),
321    POINTER(POINTER(AVDictionary))]
322avformat.avformat_close_input.restype = None
323avformat.avformat_close_input.argtypes = [
324    POINTER(POINTER(AVFormatContext))]
325avformat.av_read_frame.restype = c_int
326avformat.av_read_frame.argtypes = [POINTER(AVFormatContext),
327                                   POINTER(AVPacket)]
328avformat.av_seek_frame.restype = c_int
329avformat.av_seek_frame.argtypes = [POINTER(AVFormatContext),
330                                   c_int, c_int64, c_int]
331avformat.avformat_seek_file.restype = c_int
332avformat.avformat_seek_file.argtypes = [POINTER(AVFormatContext),
333                                        c_int, c_int64, c_int64, c_int64, c_int]
334avformat.av_guess_frame_rate.restype = AVRational
335avformat.av_guess_frame_rate.argtypes = [POINTER(AVFormatContext),
336                                         POINTER(AVStream), POINTER(AVFrame)]
337
338__all__ = [
339    'avformat',
340    'AVSEEK_FLAG_BACKWARD',
341    'AVSEEK_FLAG_BYTE',
342    'AVSEEK_FLAG_ANY',
343    'AVSEEK_FLAG_FRAME',
344    'AVFormatContext'
345]
346