Skip to content

Commit 9e69ccd

Browse files
authored
Merge pull request #176 from GetStream/feature/uni-130-user-defined-publisher-resolution-is-not-respected
Feature/uni 130 user defined publisher resolution is not respected
2 parents 6b3764b + bb6144b commit 9e69ccd

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

Packages/StreamVideo/Runtime/Core/LowLevelClient/RtcSession.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,11 @@ var mediaStreamRecord
13911391

13921392
private IEnumerable<TrackInfo> GetPublisherTracks(string sdp)
13931393
{
1394+
if (Publisher == null)
1395+
{
1396+
throw new ArgumentNullException($"{nameof(Publisher)} is null in {nameof(GetPublisherTracks)}");
1397+
}
1398+
13941399
var transceivers = Publisher.GetTransceivers().ToArray();
13951400

13961401
//StreamTodo: investigate why this return no results
@@ -1436,8 +1441,7 @@ private IEnumerable<TrackInfo> GetPublisherTracks(string sdp)
14361441

14371442
if (t.Sender.Track.Kind == TrackKind.Video)
14381443
{
1439-
var videoLayers = GetPublisherVideoLayers(Publisher.VideoSender.GetParameters().encodings,
1440-
_publisherVideoSettings);
1444+
var videoLayers = GetPublisherVideoLayers(Publisher.VideoSender.GetParameters().encodings);
14411445
trackInfo.Layers.AddRange(videoLayers);
14421446

14431447
#if STREAM_DEBUG_ENABLED
@@ -1472,8 +1476,7 @@ private string ReplaceVp8PayloadType(string sdpOffer)
14721476
return sdpOffer;
14731477
}
14741478

1475-
private IEnumerable<VideoLayer> GetPublisherVideoLayers(IEnumerable<RTCRtpEncodingParameters> encodings,
1476-
PublisherVideoSettings videoSettings)
1479+
private IEnumerable<VideoLayer> GetPublisherVideoLayers(IEnumerable<RTCRtpEncodingParameters> encodings)
14771480
{
14781481
#if STREAM_DEBUG_ENABLED
14791482
var sb = new System.Text.StringBuilder();
@@ -1482,7 +1485,7 @@ private IEnumerable<VideoLayer> GetPublisherVideoLayers(IEnumerable<RTCRtpEncodi
14821485
foreach (var encoding in encodings)
14831486
{
14841487
var scaleBy = encoding.scaleResolutionDownBy ?? 1.0;
1485-
var resolution = videoSettings.MaxResolution;
1488+
var resolution = Publisher.GetLatestVideoSettings().MaxResolution;
14861489
var width = (uint)(resolution.Width / scaleBy);
14871490
var height = (uint)(resolution.Height / scaleBy);
14881491

Packages/StreamVideo/Runtime/Core/LowLevelClient/StreamPeerConnection.cs

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ private set
8282

8383
public RTCRtpSender VideoSender { get; private set; }
8484

85+
// Full: 704×576 -> half: 352×288 -> quarter: 176×144 <- We want the smallest resolution to be above 96x96
86+
public static VideoResolution MinimumSafeTargetResolution => new VideoResolution(704, 576);
87+
8588
public StreamPeerConnection(ILogs logs, StreamPeerType peerType, IEnumerable<ICEServer> iceServers,
8689
IMediaInputProvider mediaInputProvider, IStreamAudioConfig audioConfig,
8790
PublisherVideoSettings publisherVideoSettings, Tracer tracer)
@@ -223,6 +226,18 @@ public void Update()
223226
}
224227

225228
public Task<RTCStatsReport> GetStatsReportAsync() => _peerConnection.GetStatsAsync();
229+
230+
public PublisherVideoSettings GetLatestVideoSettings()
231+
{
232+
if (_publisherVideoSettings == null)
233+
{
234+
throw new ArgumentNullException($"{nameof(_publisherVideoSettings)} is null in {nameof(GetLatestVideoSettings)}");
235+
}
236+
237+
_publisherVideoSettings.MaxResolution = PublisherTargetResolution;
238+
_publisherVideoSettings.FrameRate = PublisherTargetFrameRate;
239+
return _publisherVideoSettings;
240+
}
226241

227242
public void Dispose()
228243
{
@@ -275,14 +290,53 @@ public void Dispose()
275290
private const string VideoCodecKeyH264 = "h264";
276291
private const string VideoCodecKeyVP8 = "vp8";
277292
private const string AudioCodecKeyRed = "red";
293+
294+
private VideoResolution PublisherTargetResolution
295+
{
296+
get
297+
{
298+
if (_mediaInputProvider.VideoInput != null)
299+
{
300+
var preferred = new VideoResolution(_mediaInputProvider.VideoInput.width,
301+
_mediaInputProvider.VideoInput.height);
302+
303+
// Requesting too small resolution can cause crashes in the Android video encoder
304+
// The target resolution is used to calculate 3 layers of video encoding (full, half, quarter)
305+
// For very small values of quarter resolution (not sure exact but ~100x100) the encoder crashes
306+
307+
if (preferred.Width < MinimumSafeTargetResolution.Width ||
308+
preferred.Height < MinimumSafeTargetResolution.Height)
309+
{
310+
return MinimumSafeTargetResolution;
311+
}
312+
}
313+
314+
return _publisherVideoSettings.MaxResolution;
315+
}
316+
}
317+
318+
private uint PublisherTargetFrameRate
319+
{
320+
get
321+
{
322+
if (_mediaInputProvider.VideoInput != null)
323+
{
324+
return (uint)_mediaInputProvider.VideoInput.requestedFPS;
325+
}
326+
327+
return 30;
328+
}
329+
}
278330

279331
private readonly RTCPeerConnection _peerConnection;
280332

281333
private readonly ILogs _logs;
282334
private readonly StreamPeerType _peerType;
283335
private readonly IMediaInputProvider _mediaInputProvider;
284336
private readonly IStreamAudioConfig _audioConfig;
285-
private readonly PublisherVideoSettings _publisherVideoSettings;
337+
338+
//StreamTOdo: Finish implementation. This currently is not exposed to the user + it doesn't take into account VideoInput resolution. We need publisher resolution to match with WebCamTexture size
339+
private readonly PublisherVideoSettings _publisherVideoSettings;
286340
private readonly Tracer _tracer;
287341

288342
private readonly List<RTCIceCandidate> _pendingIceCandidates = new List<RTCIceCandidate>();
@@ -360,6 +414,7 @@ private void OnTrack(RTCTrackEvent trackEvent)
360414
var streamIds = trackEvent.Streams != null && trackEvent.Streams.Any()
361415
? string.Join(",", trackEvent.Streams.Select(s => s.Id))
362416
: "";
417+
var isEnabled = trackEvent.Track.Enabled;
363418

364419
if (!string.IsNullOrEmpty(streamIds))
365420
{
@@ -587,6 +642,10 @@ private static IEnumerable<RTCRtpEncodingParameters> GetVideoEncodingParameters(
587642

588643
break;
589644
case TrackKind.Video:
645+
646+
//StreamTodo: construct fewer layer when the target resolution is small. Android video encoder crashes when requesting very small resolution
647+
// We're currently forcing the smallest safe resolution that the user can request so that the quarter layer doesn't reach too small resolution
648+
// But we should allow setting small resolution and just produce fewer layers in that case
590649

591650
var fullQuality = new RTCRtpEncodingParameters
592651
{
@@ -631,17 +690,6 @@ private static IEnumerable<RTCRtpEncodingParameters> GetVideoEncodingParameters(
631690
}
632691
}
633692

634-
private VideoResolution GetPublisherResolution()
635-
{
636-
if (_mediaInputProvider.VideoInput != null)
637-
{
638-
var maxResolution = _publisherVideoSettings.MaxResolution;
639-
return new VideoResolution(maxResolution.Width, maxResolution.Height);
640-
}
641-
642-
return VideoResolution.Res_1080p;
643-
}
644-
645693
private VideoStreamTrack CreatePublisherVideoTrack()
646694
{
647695
if (_mediaInputProvider.VideoInput == null)
@@ -653,7 +701,7 @@ private VideoStreamTrack CreatePublisherVideoTrack()
653701
var gfxType = SystemInfo.graphicsDeviceType;
654702
var format = WebRTC.GetSupportedRenderTextureFormat(gfxType);
655703

656-
var res = GetPublisherResolution();
704+
var res = PublisherTargetResolution;
657705
_publisherVideoTrackTexture = new RenderTexture((int)res.Width, (int)res.Height, 0, format);
658706

659707
#if STREAM_DEBUG_ENABLED

0 commit comments

Comments
 (0)