File tree Expand file tree Collapse file tree 5 files changed +40
-0
lines changed
Expand file tree Collapse file tree 5 files changed +40
-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,21 @@ 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+ (p .pts , p .duration ) for p in container .demux () if p .pts is not None
56+ ]
57+ packet_durations .sort (key = lambda x : x [0 ])
58+
59+ with av .open (fate_suite ("h264/interlaced_crop.mp4" )) as container :
60+ frame_durations = [(f .pts , f .duration ) for f in container .decode (video = 0 )]
61+ frame_durations .sort (key = lambda x : x [0 ])
62+
63+ assert len (packet_durations ) == len (frame_durations )
64+ assert all (pd [1 ] == fd [1 ] for pd , fd in zip (packet_durations , frame_durations ))
65+
66+
5267def test_invalid_pixel_format () -> None :
5368 with pytest .raises (ValueError , match = "not a pixel format: '__unknown_pix_fmt'" ):
5469 VideoFrame (640 , 480 , "__unknown_pix_fmt" )
You can’t perform that action at this time.
0 commit comments