1- cimport libav as lib
2- from libc.stdint cimport int64_t
3-
4- from av.codec.context cimport CodecContext
5- from av.codec.hwaccel cimport HWAccel, HWConfig
6- from av.error cimport err_check
7- from av.frame cimport Frame
8- from av.packet cimport Packet
9- from av.utils cimport avrational_to_fraction, to_avrational
10- from av.video.format cimport VideoFormat, get_pix_fmt, get_video_format
11- from av.video.frame cimport VideoFrame, alloc_video_frame
12- from av.video.reformatter cimport VideoReformatter
13-
14-
15- cdef lib.AVPixelFormat _get_hw_format(lib.AVCodecContext * ctx, const lib.AVPixelFormat * pix_fmts) noexcept:
1+ import cython
2+ import cython .cimports .libav as lib
3+ from cython .cimports .av .codec .context import CodecContext
4+ from cython .cimports .av .codec .hwaccel import HWAccel , HWConfig
5+ from cython .cimports .av .error import err_check
6+ from cython .cimports .av .frame import Frame
7+ from cython .cimports .av .packet import Packet
8+ from cython .cimports .av .utils import avrational_to_fraction , to_avrational
9+ from cython .cimports .av .video .format import VideoFormat , get_pix_fmt , get_video_format
10+ from cython .cimports .av .video .frame import VideoFrame , alloc_video_frame
11+ from cython .cimports .av .video .reformatter import VideoReformatter
12+ from cython .cimports .libc .stdint import int64_t
13+
14+
15+ @cython .cfunc
16+ @cython .exceptval (check = False )
17+ def _get_hw_format (
18+ ctx : cython .pointer [lib .AVCodecContext ],
19+ pix_fmts : cython .pointer [cython .const [lib .AVPixelFormat ]],
20+ ) -> lib .AVPixelFormat :
1621 # In the case where we requested accelerated decoding, the decoder first calls this function
1722 # with a list that includes both the hardware format and software formats.
1823 # First we try to pick the hardware format if it's in the list.
1924 # However, if the decoder fails to initialize the hardware, it will call this function again,
2025 # with only software formats in pix_fmts. We return ctx->sw_pix_fmt regardless in this case,
2126 # because that should be in the candidate list. If not, we are out of ideas anyways.
22- cdef AVCodecPrivateData* private_data = < AVCodecPrivateData* > ctx.opaque
23- i = 0
27+ private_data : cython .pointer [AVCodecPrivateData ] = cython .cast (
28+ cython .pointer [AVCodecPrivateData ], ctx .opaque
29+ )
30+ i : cython .int = 0
2431 while pix_fmts [i ] != - 1 :
2532 if pix_fmts [i ] == private_data .hardware_pix_fmt :
2633 return pix_fmts [i ]
2734 i += 1
28- return ctx.sw_pix_fmt if private_data.allow_software_fallback else lib.AV_PIX_FMT_NONE
29-
35+ return (
36+ ctx .sw_pix_fmt if private_data .allow_software_fallback else lib .AV_PIX_FMT_NONE
37+ )
3038
31- cdef class VideoCodecContext(CodecContext):
3239
40+ @cython .cclass
41+ class VideoCodecContext (CodecContext ):
3342 def __cinit__ (self , * args , ** kwargs ):
3443 self .last_w = 0
3544 self .last_h = 0
3645
37- cdef _init(self , lib.AVCodecContext * ptr, const lib.AVCodec * codec, HWAccel hwaccel):
38- CodecContext._init(self , ptr, codec, hwaccel) # TODO: Can this be `super`?
46+ @cython .cfunc
47+ def _init (
48+ self ,
49+ ptr : cython .pointer [lib .AVCodecContext ],
50+ codec : cython .pointer [cython .const [lib .AVCodec ]],
51+ hwaccel : HWAccel | None ,
52+ ):
53+ CodecContext ._init (self , ptr , codec , hwaccel )
3954
4055 if hwaccel is not None :
4156 try :
4257 self .hwaccel_ctx = hwaccel .create (self .codec )
4358 self .ptr .hw_device_ctx = lib .av_buffer_ref (self .hwaccel_ctx .ptr )
4459 self .ptr .pix_fmt = self .hwaccel_ctx .config .ptr .pix_fmt
4560 self .ptr .get_format = _get_hw_format
46- self ._private_data.hardware_pix_fmt = self .hwaccel_ctx.config.ptr.pix_fmt
47- self ._private_data.allow_software_fallback = self .hwaccel.allow_software_fallback
48- self .ptr.opaque = & self ._private_data
61+ self ._private_data .hardware_pix_fmt = (
62+ self .hwaccel_ctx .config .ptr .pix_fmt
63+ )
64+ self ._private_data .allow_software_fallback = (
65+ self .hwaccel .allow_software_fallback
66+ )
67+ self .ptr .opaque = cython .address (self ._private_data )
4968 except NotImplementedError :
5069 # Some streams may not have a hardware decoder. For example, many action
5170 # cam videos have a low resolution mjpeg stream, which is usually not
@@ -60,20 +79,20 @@ def __cinit__(self, *args, **kwargs):
6079 self ._build_format ()
6180 self .encoded_frame_count = 0
6281
63- cdef _prepare_frames_for_encode(self , Frame input ):
64- if not input :
82+ @cython .cfunc
83+ def _prepare_frames_for_encode (self , input : Frame | None ) -> list :
84+ if input is None or not input :
6585 return [None ]
6686
67- cdef VideoFrame vframe = input
68-
6987 if self ._format is None :
7088 raise ValueError ("self._format is None, cannot encode" )
7189
90+ vframe : VideoFrame = input
7291 # Reformat if it doesn't match.
7392 if (
74- vframe.format.pix_fmt != self ._format.pix_fmt or
75- vframe.width != self .ptr.width or
76- vframe.height != self .ptr.height
93+ vframe .format .pix_fmt != self ._format .pix_fmt
94+ or vframe .width != self .ptr .width
95+ or vframe .height != self .ptr .height
7796 ):
7897 if not self .reformatter :
7998 self .reformatter = VideoReformatter ()
@@ -84,73 +103,74 @@ def __cinit__(self, *args, **kwargs):
84103
85104 # There is no pts, so create one.
86105 if vframe .ptr .pts == lib .AV_NOPTS_VALUE :
87- vframe.ptr.pts = < int64_t> self .encoded_frame_count
106+ vframe .ptr .pts = cython . cast ( int64_t , self .encoded_frame_count )
88107
89108 self .encoded_frame_count += 1
90-
91109 return [vframe ]
92110
93- cdef Frame _alloc_next_frame(self ):
111+ @cython .cfunc
112+ def _alloc_next_frame (self ) -> Frame :
94113 return alloc_video_frame ()
95114
96- cdef _setup_decoded_frame(self , Frame frame, Packet packet):
115+ @cython .cfunc
116+ def _setup_decoded_frame (self , frame : Frame , packet : Packet ):
97117 CodecContext ._setup_decoded_frame (self , frame , packet )
98- cdef VideoFrame vframe = frame
118+ vframe : VideoFrame = frame
99119 vframe ._init_user_attributes ()
100120
101- cdef _transfer_hwframe(self , Frame frame):
121+ @cython .cfunc
122+ def _transfer_hwframe (self , frame : Frame ):
102123 if self .hwaccel_ctx is None :
103124 return frame
104-
105125 if frame .ptr .format != self .hwaccel_ctx .config .ptr .pix_fmt :
106126 # If we get a software frame, that means we are in software fallback mode, and don't actually
107127 # need to transfer.
108128 return frame
109129
110- cdef Frame frame_sw
111-
112- frame_sw = self ._alloc_next_frame()
113-
130+ frame_sw : Frame = self ._alloc_next_frame ()
114131 err_check (lib .av_hwframe_transfer_data (frame_sw .ptr , frame .ptr , 0 ))
115-
116- # TODO: Is there anything else to transfer?!
132+ # TODO: Is there anything else to transfer?
117133 frame_sw .pts = frame .pts
118-
119134 return frame_sw
120135
121- cdef _build_format(self ):
122- self ._format = get_video_format(< lib.AVPixelFormat> self .ptr.pix_fmt, self .ptr.width, self .ptr.height)
136+ @cython .cfunc
137+ def _build_format (self ):
138+ self ._format = get_video_format (
139+ cython .cast (lib .AVPixelFormat , self .ptr .pix_fmt ),
140+ self .ptr .width ,
141+ self .ptr .height ,
142+ )
123143
124144 @property
125145 def format (self ):
126146 return self ._format
127147
128148 @format .setter
129- def format (self , VideoFormat format ):
149+ def format (self , format : VideoFormat ):
130150 self .ptr .pix_fmt = format .pix_fmt
131151 self .ptr .width = format .width
132152 self .ptr .height = format .height
133153 self ._build_format () # Kinda wasteful.
134154
135155 @property
136156 def width (self ):
137- if self .ptr is NULL :
157+ if self .ptr is cython . NULL :
138158 return 0
139159 return self .ptr .width
140160
141161 @width .setter
142- def width (self , unsigned int value ):
162+ def width (self , value : cython . uint ):
143163 self .ptr .width = value
144164 self ._build_format ()
145165
146166 @property
147167 def height (self ):
148- if self .ptr is NULL :
168+ if self .ptr is cython . NULL :
149169 return 0
150170 return self .ptr .height
151171
152172 @height .setter
153- def height (self , unsigned int value ):
173+ def height (self , value : cython . uint ):
154174 self .ptr .height = value
155175 self ._build_format ()
156176
@@ -160,13 +180,13 @@ def bits_per_coded_sample(self):
160180 The number of bits per sample in the codedwords. It's mandatory for this to be set for some formats to decode properly.
161181
162182 Wraps :ffmpeg:`AVCodecContext.bits_per_coded_sample`.
163-
183+
164184 :type: int
165185 """
166186 return self .ptr .bits_per_coded_sample
167-
187+
168188 @bits_per_coded_sample .setter
169- def bits_per_coded_sample (self , int value ):
189+ def bits_per_coded_sample (self , value : cython . int ):
170190 if self .is_encoder :
171191 raise ValueError ("Not supported for encoders" )
172192
@@ -194,11 +214,11 @@ def framerate(self):
194214
195215 :type: fractions.Fraction
196216 """
197- return avrational_to_fraction(& self .ptr.framerate)
217+ return avrational_to_fraction (cython . address ( self .ptr .framerate ) )
198218
199219 @framerate .setter
200220 def framerate (self , value ):
201- to_avrational(value, & self .ptr.framerate)
221+ to_avrational (value , cython . address ( self .ptr .framerate ) )
202222
203223 @property
204224 def rate (self ):
@@ -213,37 +233,39 @@ def rate(self, value):
213233 def gop_size (self ):
214234 """
215235 Sets the number of frames between keyframes. Used only for encoding.
216-
236+
217237 :type: int
218238 """
219239 if self .is_decoder :
220240 raise RuntimeError ("Cannot access 'gop_size' as a decoder" )
221241 return self .ptr .gop_size
222242
223243 @gop_size .setter
224- def gop_size (self , int value ):
244+ def gop_size (self , value : cython . int ):
225245 if self .is_decoder :
226246 raise RuntimeError ("Cannot access 'gop_size' as a decoder" )
227247 self .ptr .gop_size = value
228248
229249 @property
230250 def sample_aspect_ratio (self ):
231- return avrational_to_fraction(& self .ptr.sample_aspect_ratio)
251+ return avrational_to_fraction (cython . address ( self .ptr .sample_aspect_ratio ) )
232252
233253 @sample_aspect_ratio .setter
234254 def sample_aspect_ratio (self , value ):
235- to_avrational(value, & self .ptr.sample_aspect_ratio)
255+ to_avrational (value , cython . address ( self .ptr .sample_aspect_ratio ) )
236256
237257 @property
238258 def display_aspect_ratio (self ):
239- cdef lib.AVRational dar
240-
259+ dar : lib .AVRational
241260 lib .av_reduce (
242- & dar.num, & dar.den,
261+ cython .address (dar .num ),
262+ cython .address (dar .den ),
243263 self .ptr .width * self .ptr .sample_aspect_ratio .num ,
244- self .ptr.height * self .ptr.sample_aspect_ratio.den, 1024 * 1024 )
264+ self .ptr .height * self .ptr .sample_aspect_ratio .den ,
265+ 1024 * 1024 ,
266+ )
245267
246- return avrational_to_fraction(& dar)
268+ return avrational_to_fraction (cython . address ( dar ) )
247269
248270 @property
249271 def has_b_frames (self ):
0 commit comments