File tree Expand file tree Collapse file tree 5 files changed +42
-0
lines changed
Expand file tree Collapse file tree 5 files changed +42
-0
lines changed Original file line number Diff line number Diff line change @@ -9,6 +9,7 @@ class SideData(TypedDict, total=False):
99class Frame :
1010 dts : int | None
1111 pts : int | None
12+ duration : int | None
1213 time_base : Fraction
1314 side_data : SideData
1415 opaque : object
Original file line number Diff line number Diff line change @@ -53,6 +53,9 @@ cdef class Frame:
5353 if self .ptr.pts != lib.AV_NOPTS_VALUE:
5454 self .ptr.pts = lib.av_rescale_q(self .ptr.pts, self ._time_base, dst)
5555
56+ if self .ptr.duration != 0 :
57+ self .ptr.duration = lib.av_rescale_q(self .ptr.duration, self ._time_base, dst)
58+
5659 self ._time_base = dst
5760
5861 @property
@@ -95,6 +98,24 @@ cdef class Frame:
9598 else :
9699 self .ptr.pts = value
97100
101+ @property
102+ def duration (self ):
103+ """
104+ The duration of the frame in :attr:`time_base` units
105+
106+ :type: int
107+ """
108+ if self .ptr.duration == 0 :
109+ return None
110+ return self .ptr.duration
111+
112+ @duration.setter
113+ def duration (self , value ):
114+ if value is None :
115+ self .ptr.duration = 0
116+ else :
117+ self .ptr.duration = value
118+
98119 @property
99120 def time (self ):
100121 """
Original file line number Diff line number Diff line change @@ -30,6 +30,7 @@ class PictureType(IntEnum):
3030class VideoFrame (Frame ):
3131 format : VideoFormat
3232 pts : int
33+ duration : int
3334 planes : tuple [VideoPlane , ...]
3435 pict_type : int
3536 colorspace : int
Original file line number Diff line number Diff line change @@ -461,6 +461,8 @@ cdef extern from "libavcodec/avcodec.h" nogil:
461461 AVColorTransferCharacteristic color_trc
462462 AVColorSpace colorspace
463463
464+ int64_t duration
465+
464466 cdef AVFrame* avcodec_alloc_frame()
465467
466468 cdef struct AVPacket:
Original file line number Diff line number Diff line change @@ -49,6 +49,23 @@ def test_opaque() -> None:
4949 assert type (frame .opaque ) is tuple and len (frame .opaque ) == 2
5050
5151
52+ def test_frame_duration_matches_packet () -> None :
53+ with av .open (fate_suite ("h264/interlaced_crop.mp4" )) as container :
54+ packet_durations = []
55+ frame_durations = []
56+ for packet in container .demux ():
57+ if packet .pts is not None :
58+ packet_durations .append ((packet .pts , packet .duration ))
59+ for frame in packet .decode ():
60+ if frame .pts is not None :
61+ frame_durations .append ((frame .pts , frame .duration ))
62+
63+ packet_durations .sort (key = lambda x : x [0 ])
64+ frame_durations .sort (key = lambda x : x [0 ])
65+
66+ assert all (pd [1 ] == fd [1 ] for pd , fd in zip (packet_durations , frame_durations ))
67+
68+
5269def test_invalid_pixel_format () -> None :
5370 with pytest .raises (ValueError , match = "not a pixel format: '__unknown_pix_fmt'" ):
5471 VideoFrame (640 , 480 , "__unknown_pix_fmt" )
You can’t perform that action at this time.
0 commit comments