1- cimport libav as lib
2- from libc.string cimport memcpy
1+ # type: ignore
2+ import cython
3+ from cython import NULL
4+ from cython .cimports import libav as lib
5+ from cython .cimports .av .error import stash_exception
6+ from cython .cimports .libc .stdint import int64_t , uint8_t
7+ from cython .cimports .libc .string import memcpy
38
4- from av.error cimport stash_exception
9+ Buf = cython .typedef (cython .pointer [uint8_t ])
10+ BufC = cython .typedef (cython .pointer [cython .const [uint8_t ]])
511
6- ctypedef int64_t (* seek_func_t)(void * opaque, int64_t offset, int whence) noexcept nogil
12+ seek_func_t = cython .typedef (
13+ "int64_t (*seek_func_t)(void *opaque, int64_t offset, int whence) noexcept nogil"
14+ )
715
816
9- cdef class PyIOFile:
17+ @cython .cclass
18+ class PyIOFile :
1019 def __cinit__ (self , file , buffer_size , writeable = None ):
1120 self .file = file
1221
13- cdef seek_func_t seek_func = NULL
22+ seek_func : seek_func_t = NULL
1423
1524 readable = getattr (self .file , "readable" , None )
1625 writable = getattr (self .file , "writable" , None )
@@ -21,70 +30,81 @@ def __cinit__(self, file, buffer_size, writeable=None):
2130 self .ftell = getattr (self .file , "tell" , None )
2231 self .fclose = getattr (self .file , "close" , None )
2332
24- # To be seekable the file object must have `seek` and `tell` methods.
33+ # To be seekable, the file object must have `seek` and `tell` methods.
2534 # If it also has a `seekable` method, it must return True.
2635 if (
2736 self .fseek is not None
2837 and self .ftell is not None
2938 and (seekable is None or seekable ())
3039 ):
31- seek_func = pyio_seek
40+ seek_func : seek_func_t = pyio_seek
3241
3342 if writeable is None :
3443 writeable = self .fwrite is not None
3544
3645 if writeable :
3746 if self .fwrite is None or (writable is not None and not writable ()):
38- raise ValueError (" File object has no write() method, or writable() returned False." )
47+ raise ValueError (
48+ "File object has no write() method, or writable() returned False."
49+ )
3950 else :
4051 if self .fread is None or (readable is not None and not readable ()):
41- raise ValueError (" File object has no read() method, or readable() returned False." )
52+ raise ValueError (
53+ "File object has no read() method, or readable() returned False."
54+ )
4255
4356 self .pos = 0
4457 self .pos_is_valid = True
4558
4659 # This is effectively the maximum size of reads.
47- self .buffer = < unsigned char * > lib.av_malloc(buffer_size)
60+ self .buffer = cython . cast ( cython . p_uchar , lib .av_malloc (buffer_size ) )
4861
4962 self .iocontext = lib .avio_alloc_context (
5063 self .buffer ,
5164 buffer_size ,
5265 writeable ,
53- < void * > self , # User data.
66+ cython . cast ( cython . p_void , self ) , # User data.
5467 pyio_read ,
5568 pyio_write ,
56- seek_func
69+ seek_func ,
5770 )
5871
5972 if seek_func :
6073 self .iocontext .seekable = lib .AVIO_SEEKABLE_NORMAL
6174 self .iocontext .max_packet_size = buffer_size
6275
6376 def __dealloc__ (self ):
64- with nogil:
77+ with cython . nogil :
6578 # FFmpeg will not release custom input, so it's up to us to free it.
6679 # Do not touch our original buffer as it may have been freed and replaced.
6780 if self .iocontext :
68- lib.av_freep(& self .iocontext.buffer)
69- lib.av_freep(& self .iocontext)
81+ lib .av_freep (cython . address ( self .iocontext .buffer ) )
82+ lib .av_freep (cython . address ( self .iocontext ) )
7083
71- # We likely errored badly if we got here, and so are still
72- # responsible for our buffer.
84+ # We likely errored badly if we got here, and so we are still responsible.
7385 else :
74- lib.av_freep(& self .buffer)
86+ lib .av_freep (cython . address ( self .buffer ) )
7587
7688
77- cdef int pyio_read(void * opaque, uint8_t * buf, int buf_size) noexcept nogil:
78- with gil:
89+ @cython .cfunc
90+ @cython .nogil
91+ @cython .exceptval (check = False )
92+ def pyio_read (opaque : cython .p_void , buf : Buf , buf_size : cython .int ) -> cython .int :
93+ with cython .gil :
7994 return pyio_read_gil (opaque , buf , buf_size )
8095
81- cdef int pyio_read_gil(void * opaque, uint8_t * buf, int buf_size) noexcept:
82- cdef PyIOFile self
83- cdef bytes res
96+
97+ @cython .cfunc
98+ @cython .exceptval (check = False )
99+ def pyio_read_gil (opaque : cython .p_void , buf : Buf , buf_size : cython .int ) -> cython .int :
100+ self : PyIOFile
101+ res : bytes
84102 try :
85- self = < PyIOFile> opaque
103+ self = cython . cast ( PyIOFile , opaque )
86104 res = self .fread (buf_size )
87- memcpy(buf, < void * >< char * > res, len (res))
105+ memcpy (
106+ buf , cython .cast (cython .p_void , cython .cast (cython .p_char , res )), len (res )
107+ )
88108 self .pos += len (res )
89109 if not res :
90110 return lib .AVERROR_EOF
@@ -93,16 +113,24 @@ def __dealloc__(self):
93113 return stash_exception ()
94114
95115
96- cdef int pyio_write(void * opaque, const uint8_t * buf, int buf_size) noexcept nogil:
97- with gil:
116+ @cython .cfunc
117+ @cython .nogil
118+ @cython .exceptval (check = False )
119+ def pyio_write (opaque : cython .p_void , buf : BufC , buf_size : cython .int ) -> cython .int :
120+ with cython .gil :
98121 return pyio_write_gil (opaque , buf , buf_size )
99122
100- cdef int pyio_write_gil(void * opaque, const uint8_t * buf, int buf_size) noexcept:
101- cdef PyIOFile self
102- cdef bytes bytes_to_write
103- cdef int bytes_written
123+
124+ @cython .cfunc
125+ @cython .exceptval (check = False )
126+ def pyio_write_gil (
127+ opaque : cython .p_void , buf : BufC , buf_size : cython .int
128+ ) -> cython .int :
129+ self : PyIOFile
130+ bytes_to_write : bytes
131+ bytes_written : cython .int
104132 try :
105- self = < PyIOFile> opaque
133+ self = cython . cast ( PyIOFile , opaque )
106134 bytes_to_write = buf [:buf_size ]
107135 ret_value = self .fwrite (bytes_to_write )
108136 bytes_written = ret_value if isinstance (ret_value , int ) else buf_size
@@ -112,19 +140,25 @@ def __dealloc__(self):
112140 return stash_exception ()
113141
114142
115- cdef int64_t pyio_seek(void * opaque, int64_t offset, int whence) noexcept nogil:
116- # Seek takes the standard flags, but also a ad-hoc one which means that
117- # the library wants to know how large the file is. We are generally
118- # allowed to ignore this.
143+ @cython .cfunc
144+ @cython .nogil
145+ @cython .exceptval (check = False )
146+ def pyio_seek (opaque : cython .p_void , offset : int64_t , whence : cython .int ) -> int64_t :
147+ # Seek takes the standard flags, but also a ad-hoc one which means that the library
148+ # wants to know how large the file is. We are generally allowed to ignore this.
119149 if whence == lib .AVSEEK_SIZE :
120150 return - 1
121- with gil:
151+ with cython . gil :
122152 return pyio_seek_gil (opaque , offset , whence )
123153
124- cdef int64_t pyio_seek_gil(void * opaque, int64_t offset, int whence):
125- cdef PyIOFile self
154+
155+ @cython .cfunc
156+ def pyio_seek_gil (
157+ opaque : cython .p_void , offset : int64_t , whence : cython .int
158+ ) -> int64_t :
159+ self : PyIOFile
126160 try :
127- self = < PyIOFile> opaque
161+ self = cython . cast ( PyIOFile , opaque )
128162 res = self .fseek (offset , whence )
129163
130164 # Track the position for the user.
@@ -144,18 +178,19 @@ def __dealloc__(self):
144178 return stash_exception ()
145179
146180
147- cdef int pyio_close_gil(lib.AVIOContext * pb):
181+ @cython .cfunc
182+ def pyio_close_gil (pb : cython .pointer [lib .AVIOContext ]) -> cython .int :
148183 try :
149184 return lib .avio_close (pb )
150-
151185 except Exception :
152186 stash_exception ()
153187
154188
155- cdef int pyio_close_custom_gil(lib.AVIOContext * pb):
156- cdef PyIOFile self
189+ @cython .cfunc
190+ def pyio_close_custom_gil (pb : cython .pointer [lib .AVIOContext ]) -> cython .int :
191+ self : PyIOFile
157192 try :
158- self = < PyIOFile> pb.opaque
193+ self = cython . cast ( PyIOFile , pb .opaque )
159194
160195 # Flush bytes in the AVIOContext buffers to the custom I/O
161196 lib .avio_flush (pb )
@@ -164,6 +199,5 @@ def __dealloc__(self):
164199 self .fclose ()
165200
166201 return 0
167-
168202 except Exception :
169203 stash_exception ()
0 commit comments