Skip to content

Commit 80b45fe

Browse files
authored
Merge pull request #231 from GetStream/fix/configurable-video-buffering
feat: configurable video frame buffering with blackhole drain
2 parents 4e3c87d + d28776c commit 80b45fe

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

getstream/video/rtc/connection_manager.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def __init__(
5858
create: bool = True,
5959
subscription_config: Optional[SubscriptionConfig] = None,
6060
max_join_retries: int = 3,
61+
drain_video_frames: bool = False,
6162
**kwargs: Any,
6263
):
6364
super().__init__()
@@ -90,7 +91,9 @@ def __init__(
9091
self._subscription_manager: SubscriptionManager = SubscriptionManager(
9192
self, subscription_config
9293
)
93-
self._peer_manager: PeerConnectionManager = PeerConnectionManager(self)
94+
self._peer_manager: PeerConnectionManager = PeerConnectionManager(
95+
self, drain_video_frames=drain_video_frames
96+
)
9497

9598
self.recording_manager = self._recording_manager
9699
self.participants_state = self._participants_state

getstream/video/rtc/pc.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any, Optional
44

55
import aiortc
6-
from aiortc.contrib.media import MediaRelay
6+
from aiortc.contrib.media import MediaBlackhole, MediaRelay
77
from aiortc.mediastreams import MediaStreamTrack
88
from aiortc.rtcrtpparameters import RTCRtpCodecCapability
99
from aiortc.rtcrtpsender import RTCRtpSender
@@ -131,15 +131,19 @@ def __init__(
131131
self,
132132
connection,
133133
configuration: aiortc.RTCConfiguration,
134+
drain_video_frames: bool = False,
134135
) -> None:
135136
logger.info(
136137
f"creating subscriber peer connection with configuration: {configuration}"
137138
)
138139
super().__init__(configuration)
139140
self.connection = connection
141+
self._drain_video_frames = drain_video_frames
140142

141143
self.track_map = {} # track_id -> (MediaRelay, original_track)
142144
self.video_frame_trackers = {} # track_id -> VideoFrameTracker
145+
self._video_blackholes: dict[str, MediaBlackhole] = {}
146+
self._video_drain_tasks: dict[str, asyncio.Task] = {}
143147

144148
@self.on("track")
145149
async def on_track(track: aiortc.mediastreams.MediaStreamTrack):
@@ -177,7 +181,20 @@ def _emit_pcm(pcm: PcmData):
177181
handler = AudioTrackHandler(relay.subscribe(tracked_track), _emit_pcm)
178182
asyncio.create_task(handler.start())
179183

180-
self.emit("track_added", relay.subscribe(tracked_track), user)
184+
proxy = relay.subscribe(tracked_track)
185+
186+
# Drain unconsumed video frames to prevent unbounded queue growth
187+
# in RTCRtpReceiver (aiortc issue #554)
188+
if track.kind == "video" and self._drain_video_frames:
189+
drain_proxy = relay.subscribe(tracked_track)
190+
blackhole = MediaBlackhole()
191+
blackhole.addTrack(drain_proxy)
192+
self._video_blackholes[track.id] = blackhole
193+
self._video_drain_tasks[track.id] = asyncio.create_task(
194+
blackhole.start()
195+
)
196+
197+
self.emit("track_added", proxy, user)
181198

182199
@self.on("icegatheringstatechange")
183200
def on_icegatheringstatechange():

getstream/video/rtc/peer_connection.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
class PeerConnectionManager:
2929
"""Manages WebRTC peer connections for publishing and subscribing."""
3030

31-
def __init__(self, connection_manager):
31+
def __init__(self, connection_manager, drain_video_frames: bool = False):
3232
self.connection_manager = connection_manager
33+
self._drain_video_frames = drain_video_frames
3334
self.publisher_pc: Optional[PublisherPeerConnection] = None
3435
self.subscriber_pc: Optional[SubscriberPeerConnection] = None
3536
self.publisher_negotiation_lock = asyncio.Lock()
@@ -47,6 +48,7 @@ async def setup_subscriber(self):
4748
self.subscriber_pc = SubscriberPeerConnection(
4849
connection=self.connection_manager,
4950
configuration=self._build_rtc_configuration(),
51+
drain_video_frames=self._drain_video_frames,
5052
)
5153

5254
# Trace create event

0 commit comments

Comments
 (0)