Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Features:
- ``VideoFrame.from_dlpack`` no longer requires restating ``primary_ctx``/``current_ctx`` when passing an explicit ``cuda_context``; the flags are only validated when explicitly given by :gh-user:`WyattBlue`.
- Support passing an explicit CUDA stream to FFmpeg CUDA operations, including NVENC input and output, via a ``cuda_stream`` parameter on ``CudaContext``; currently limited to logical CUDA device 0 by :gh-user:`Yozer` (:pr:`2360`).
- ``VideoFrame.save`` now forwards keyword arguments to the encoder, letting callers trade file size for speed (e.g. ``pred="none"`` or ``compression_level=1`` for PNG, ``qscale=2`` for JPG) by :gh-user:`WyattBlue`.
- Add ``InputContainer.start_time_realtime``, the stream's start time in microseconds since the Unix epoch, which RTSP derives from RTCP sender reports, by :gh-user:`WyattBlue` (:issue:`2365`).

Fixes:

Expand Down
14 changes: 14 additions & 0 deletions av/container/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ def start_time(self):
if self.ptr.start_time != lib.AV_NOPTS_VALUE:
return self.ptr.start_time

@property
def start_time_realtime(self):
"""Start time of the stream in real world time, in microseconds since the
Unix epoch, or ``None`` if unknown.

Only a few demuxers know this; RTSP computes it from RTCP sender reports,
which is what makes it useful for aligning analytics with a camera's clock.

Wraps :ffmpeg:`AVFormatContext.start_time_realtime`.
"""
self._assert_open()
if self.ptr.start_time_realtime != lib.AV_NOPTS_VALUE:
return self.ptr.start_time_realtime

@property
def duration(self):
self._assert_open()
Expand Down
1 change: 1 addition & 0 deletions av/container/input.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ from .core import Container

class InputContainer(Container):
start_time: int
start_time_realtime: int | None
duration: int | None
bit_rate: int
size: int
Expand Down
1 change: 1 addition & 0 deletions include/avformat.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ cdef extern from "libavformat/avformat.h" nogil:
AVIOInterruptCB interrupt_callback
AVDictionary *metadata
int64_t start_time
int64_t start_time_realtime
int64_t duration
int64_t bit_rate
int flags
Expand Down
2 changes: 2 additions & 0 deletions tests/test_file_probing.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def test_container_probing(self) -> None:
assert self.file.metadata == {}
assert self.file.size == 207740
assert self.file.start_time == 1400000
# Only RTSP-like inputs carry a wall clock; a plain file has none.
assert self.file.start_time_realtime is None
assert len(self.file.streams) == 1

def test_stream_probing(self) -> None:
Expand Down
Loading