Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/selkies/webrtc/codecs/base.py: 50%

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

22 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 

34from abc import ABCMeta, abstractmethod 

35from fractions import Fraction 

36from typing import Any, Optional 

37 

38 

39class EncodedPacket: 

40 """A pre-encoded media sample on the WebRTC send path: the encoder's output 

41 buffer with its presentation timestamp and clock. 

42 

43 It is what pixelflux/pcmflux hand the packers, replacing `av.Packet` as the 

44 passthrough container so packing pulls in no libav wrapper and allocates no 

45 per-frame FFmpeg object. `data` is any buffer-protocol object (the encoder's 

46 own memory), referenced and never copied; packers walk it through 

47 `memoryview(packet.data)` and materialize bytes only for the RTP payloads 

48 they emit. Keeping the whole-frame copy out of the path both cuts latency 

49 and frees the GIL that a `bytes(frame)` copy would hold for the memcpy. 

50 `keyframe` says whether the sample decodes on its own, as the encoder 

51 reported it; audio samples always do. `timing` is a video frame's capture, 

52 encode-start, and encode-end instants in CLOCK_MONOTONIC nanoseconds as the 

53 capture library stamped them, or None where it did not. `dependency` is a 

54 video frame's own id and the id of the frame it predicts from (None for a 

55 frame predicting from nothing), where the encoder tracks its references 

56 and can be told to leave a lost frame out of them; None where it cannot. 

57 `codec` is the MIME type of the codec a video frame was coded with, as its 

58 capture names it, or None where the source does not say. `anchor` says a 

59 video delta frame is a long-term reference predicting from a frame every 

60 peer holds, which every peer can decode. 

61 """ 

62 

63 __slots__ = ("data", "pts", "dts", "time_base", "keyframe", "timing", "dependency", "codec", "anchor") 

64 

65 def __init__(self, data: Any, pts: Optional[int] = None, 

66 time_base: Optional[Fraction] = None, keyframe: bool = True, 

67 timing: Optional[tuple] = None, 

68 dependency: Optional[tuple] = None, 

69 codec: Optional[str] = None, anchor: bool = False) -> None: 

70 self.data = data 

71 self.pts = pts 

72 self.dts = pts 

73 self.time_base = time_base 

74 self.keyframe = keyframe 

75 self.timing = timing 

76 self.dependency = dependency 

77 self.codec = codec 

78 self.anchor = anchor 

79 

80 def __len__(self) -> int: 

81 return len(self.data) 

82 

83 

84class Decoder: 

85 """Receive-codec marker. Decoding of the browser uplink is done by pcmflux 

86 (audio) and pixelflux (video), which the encoded frames are routed to, so a 

87 registry decoder carries only the codec's identity, no libav decode.""" 

88 

89 

90class Encoder(metaclass=ABCMeta): 

91 """Packs frames a pixelflux/pcmflux encoder has already produced into RTP 

92 payloads. Encoding itself lives in those libraries, not here.""" 

93 

94 @abstractmethod 

95 def pack(self, packet: EncodedPacket) -> tuple[list[bytes], int, bool]: 

96 """The RTP payloads of one frame, its RTP timestamp, and whether the 

97 frame is a key frame (read from the bitstream; always False for audio).""" 

98 pass # pragma: no cover