Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/selkies/webrtc/clock.py: 44%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

25 statements  

1# This Source Code Form is subject to the terms of the Mozilla Public 

2# License, v. 2.0. If a copy of the MPL was not distributed with this 

3# file, You can obtain one at https://mozilla.org/MPL/2.0/. 

4# 

5# This file incorporates work covered by the following copyright and 

6# permission notice: 

7# 

8# Copyright (c) Jeremy Lainé. 

9# All rights reserved. 

10# 

11# Redistribution and use in source and binary forms, with or without 

12# modification, are permitted provided that the following conditions are met: 

13# 

14# * Redistributions of source code must retain the above copyright notice, 

15# this list of conditions and the following disclaimer. 

16# * Redistributions in binary form must reproduce the above copyright notice, 

17# this list of conditions and the following disclaimer in the documentation 

18# and/or other materials provided with the distribution. 

19# * Neither the name of aiortc nor the names of its contributors may 

20# be used to endorse or promote products derived from this software without 

21# specific prior written permission. 

22# 

23# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

24# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

25# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

26# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 

27# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 

28# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 

29# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 

30# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 

31# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 

32# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

33 

34import datetime 

35import time 

36 

37NTP_EPOCH = datetime.datetime(1900, 1, 1, tzinfo=datetime.timezone.utc) 

38# Seconds from the NTP epoch to the Unix epoch. 

39NTP_UNIX_OFFSET = 2208988800 

40 

41# The NTP clock the senders stamp and report is CLOCK_MONOTONIC placed on the 

42# wall clock once, as libwebrtc's is: a capture instant the capture library 

43# stamped on CLOCK_MONOTONIC maps into it exactly, and a step of the wall clock 

44# never moves it between two sender reports. 

45_NTP_OFFSET_NS = time.time_ns() + NTP_UNIX_OFFSET * 1_000_000_000 - time.monotonic_ns() 

46 

47 

48def current_datetime() -> datetime.datetime: 

49 return datetime.datetime.now(datetime.timezone.utc) 

50 

51 

52def current_ms() -> int: 

53 delta = current_datetime() - NTP_EPOCH 

54 return int(delta.total_seconds() * 1000) 

55 

56 

57def ntp_from_monotonic_ns(instant_ns: int) -> int: 

58 """The 64-bit NTP timestamp of a CLOCK_MONOTONIC instant in nanoseconds.""" 

59 seconds, rest = divmod(instant_ns + _NTP_OFFSET_NS, 1_000_000_000) 

60 return ((seconds & 0xFFFFFFFF) << 32) | ((rest << 32) // 1_000_000_000) 

61 

62 

63def current_ntp_time() -> int: 

64 """The NTP timestamp now: every RTP packet stamps one, so no datetime is 

65 built on the way.""" 

66 return ntp_from_monotonic_ns(time.monotonic_ns()) 

67 

68 

69def datetime_from_ntp(ntp: int) -> datetime.datetime: 

70 seconds = ntp >> 32 

71 microseconds = ((ntp & 0xFFFFFFFF) * 1000000) / (1 << 32) 

72 return NTP_EPOCH + datetime.timedelta(seconds=seconds, microseconds=microseconds) 

73 

74 

75def datetime_to_ntp(dt: datetime.datetime) -> int: 

76 delta = dt - NTP_EPOCH 

77 high = int(delta.total_seconds()) 

78 low = round((delta.microseconds * (1 << 32)) // 1000000) 

79 return (high << 32) | low