Committed by
GitHub
Allow setting of degradation preference (#420)
* Allow setting of degradation preference * fix tests * spotless
正在显示
5 个修改的文件
包含
102 行增加
和
6 行删除
| @@ -465,7 +465,6 @@ internal fun isSVCCodec(codec: String?): Boolean { | @@ -465,7 +465,6 @@ internal fun isSVCCodec(codec: String?): Boolean { | ||
| 465 | /** | 465 | /** |
| 466 | * @suppress | 466 | * @suppress |
| 467 | */ | 467 | */ |
| 468 | -@VisibleForTesting | ||
| 469 | data class TrackBitrateInfo( | 468 | data class TrackBitrateInfo( |
| 470 | val codec: String, | 469 | val codec: String, |
| 471 | val maxBitrate: Long, | 470 | val maxBitrate: Long, |
| @@ -474,7 +473,6 @@ data class TrackBitrateInfo( | @@ -474,7 +473,6 @@ data class TrackBitrateInfo( | ||
| 474 | /** | 473 | /** |
| 475 | * @suppress | 474 | * @suppress |
| 476 | */ | 475 | */ |
| 477 | -@VisibleForTesting | ||
| 478 | sealed class TrackBitrateInfoKey { | 476 | sealed class TrackBitrateInfoKey { |
| 479 | data class Cid(val value: String) : TrackBitrateInfoKey() | 477 | data class Cid(val value: String) : TrackBitrateInfoKey() |
| 480 | data class Transceiver(val value: RtpTransceiver) : TrackBitrateInfoKey() | 478 | data class Transceiver(val value: RtpTransceiver) : TrackBitrateInfoKey() |
| @@ -31,7 +31,19 @@ import io.livekit.android.room.DefaultsManager | @@ -31,7 +31,19 @@ import io.livekit.android.room.DefaultsManager | ||
| 31 | import io.livekit.android.room.RTCEngine | 31 | import io.livekit.android.room.RTCEngine |
| 32 | import io.livekit.android.room.TrackBitrateInfo | 32 | import io.livekit.android.room.TrackBitrateInfo |
| 33 | import io.livekit.android.room.isSVCCodec | 33 | import io.livekit.android.room.isSVCCodec |
| 34 | -import io.livekit.android.room.track.* | 34 | +import io.livekit.android.room.track.DataPublishReliability |
| 35 | +import io.livekit.android.room.track.LocalAudioTrack | ||
| 36 | +import io.livekit.android.room.track.LocalAudioTrackOptions | ||
| 37 | +import io.livekit.android.room.track.LocalScreencastVideoTrack | ||
| 38 | +import io.livekit.android.room.track.LocalTrackPublication | ||
| 39 | +import io.livekit.android.room.track.LocalVideoTrack | ||
| 40 | +import io.livekit.android.room.track.LocalVideoTrackOptions | ||
| 41 | +import io.livekit.android.room.track.Track | ||
| 42 | +import io.livekit.android.room.track.TrackException | ||
| 43 | +import io.livekit.android.room.track.TrackPublication | ||
| 44 | +import io.livekit.android.room.track.VideoCaptureParameter | ||
| 45 | +import io.livekit.android.room.track.VideoCodec | ||
| 46 | +import io.livekit.android.room.track.VideoEncoding | ||
| 35 | import io.livekit.android.room.util.EncodingUtils | 47 | import io.livekit.android.room.util.EncodingUtils |
| 36 | import io.livekit.android.util.LKLog | 48 | import io.livekit.android.util.LKLog |
| 37 | import io.livekit.android.webrtc.sortVideoCodecPreferences | 49 | import io.livekit.android.webrtc.sortVideoCodecPreferences |
| @@ -41,8 +53,14 @@ import livekit.LivekitModels | @@ -41,8 +53,14 @@ import livekit.LivekitModels | ||
| 41 | import livekit.LivekitRtc | 53 | import livekit.LivekitRtc |
| 42 | import livekit.LivekitRtc.AddTrackRequest | 54 | import livekit.LivekitRtc.AddTrackRequest |
| 43 | import livekit.LivekitRtc.SimulcastCodec | 55 | import livekit.LivekitRtc.SimulcastCodec |
| 44 | -import livekit.org.webrtc.* | 56 | +import livekit.org.webrtc.EglBase |
| 57 | +import livekit.org.webrtc.PeerConnectionFactory | ||
| 58 | +import livekit.org.webrtc.RtpParameters | ||
| 59 | +import livekit.org.webrtc.RtpTransceiver | ||
| 45 | import livekit.org.webrtc.RtpTransceiver.RtpTransceiverInit | 60 | import livekit.org.webrtc.RtpTransceiver.RtpTransceiverInit |
| 61 | +import livekit.org.webrtc.SurfaceTextureHelper | ||
| 62 | +import livekit.org.webrtc.VideoCapturer | ||
| 63 | +import livekit.org.webrtc.VideoProcessor | ||
| 46 | import javax.inject.Named | 64 | import javax.inject.Named |
| 47 | import kotlin.math.max | 65 | import kotlin.math.max |
| 48 | 66 | ||
| @@ -412,10 +430,14 @@ internal constructor( | @@ -412,10 +430,14 @@ internal constructor( | ||
| 412 | } | 430 | } |
| 413 | } | 431 | } |
| 414 | 432 | ||
| 415 | - // Set preferred video codec order | ||
| 416 | if (options is VideoTrackPublishOptions) { | 433 | if (options is VideoTrackPublishOptions) { |
| 434 | + // Set preferred video codec order | ||
| 417 | transceiver.sortVideoCodecPreferences(options.videoCodec, capabilitiesGetter) | 435 | transceiver.sortVideoCodecPreferences(options.videoCodec, capabilitiesGetter) |
| 418 | (track as LocalVideoTrack).codec = options.videoCodec | 436 | (track as LocalVideoTrack).codec = options.videoCodec |
| 437 | + | ||
| 438 | + val rtpParameters = transceiver.sender.parameters | ||
| 439 | + rtpParameters.degradationPreference = options.degradationPreference | ||
| 440 | + transceiver.sender.parameters = rtpParameters | ||
| 419 | } | 441 | } |
| 420 | 442 | ||
| 421 | val publication = LocalTrackPublication( | 443 | val publication = LocalTrackPublication( |
| @@ -877,6 +899,14 @@ abstract class BaseVideoTrackPublishOptions { | @@ -877,6 +899,14 @@ abstract class BaseVideoTrackPublishOptions { | ||
| 877 | * will automatically publish a secondary track encoded with the backup codec. | 899 | * will automatically publish a secondary track encoded with the backup codec. |
| 878 | */ | 900 | */ |
| 879 | abstract val backupCodec: BackupVideoCodec? | 901 | abstract val backupCodec: BackupVideoCodec? |
| 902 | + | ||
| 903 | + /** | ||
| 904 | + * When bandwidth is constrained, this preference indicates which is preferred | ||
| 905 | + * between degrading resolution vs. framerate. | ||
| 906 | + * | ||
| 907 | + * null value indicates default value (maintain framerate). | ||
| 908 | + */ | ||
| 909 | + abstract val degradationPreference: RtpParameters.DegradationPreference? | ||
| 880 | } | 910 | } |
| 881 | 911 | ||
| 882 | data class VideoTrackPublishDefaults( | 912 | data class VideoTrackPublishDefaults( |
| @@ -885,6 +915,7 @@ data class VideoTrackPublishDefaults( | @@ -885,6 +915,7 @@ data class VideoTrackPublishDefaults( | ||
| 885 | override val videoCodec: String = VideoCodec.VP8.codecName, | 915 | override val videoCodec: String = VideoCodec.VP8.codecName, |
| 886 | override val scalabilityMode: String? = null, | 916 | override val scalabilityMode: String? = null, |
| 887 | override val backupCodec: BackupVideoCodec? = null, | 917 | override val backupCodec: BackupVideoCodec? = null, |
| 918 | + override val degradationPreference: RtpParameters.DegradationPreference? = null, | ||
| 888 | ) : BaseVideoTrackPublishOptions() | 919 | ) : BaseVideoTrackPublishOptions() |
| 889 | 920 | ||
| 890 | data class VideoTrackPublishOptions( | 921 | data class VideoTrackPublishOptions( |
| @@ -896,6 +927,7 @@ data class VideoTrackPublishOptions( | @@ -896,6 +927,7 @@ data class VideoTrackPublishOptions( | ||
| 896 | override val backupCodec: BackupVideoCodec? = null, | 927 | override val backupCodec: BackupVideoCodec? = null, |
| 897 | override val source: Track.Source? = null, | 928 | override val source: Track.Source? = null, |
| 898 | override val stream: String? = null, | 929 | override val stream: String? = null, |
| 930 | + override val degradationPreference: RtpParameters.DegradationPreference? = null, | ||
| 899 | ) : BaseVideoTrackPublishOptions(), TrackPublishOptions { | 931 | ) : BaseVideoTrackPublishOptions(), TrackPublishOptions { |
| 900 | constructor( | 932 | constructor( |
| 901 | name: String? = null, | 933 | name: String? = null, |
| @@ -911,6 +943,7 @@ data class VideoTrackPublishOptions( | @@ -911,6 +943,7 @@ data class VideoTrackPublishOptions( | ||
| 911 | backupCodec = base.backupCodec, | 943 | backupCodec = base.backupCodec, |
| 912 | source = source, | 944 | source = source, |
| 913 | stream = stream, | 945 | stream = stream, |
| 946 | + degradationPreference = base.degradationPreference, | ||
| 914 | ) | 947 | ) |
| 915 | 948 | ||
| 916 | fun createBackupOptions(): VideoTrackPublishOptions? { | 949 | fun createBackupOptions(): VideoTrackPublishOptions? { |
| @@ -16,11 +16,30 @@ | @@ -16,11 +16,30 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.test.mock | 17 | package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | +import livekit.org.webrtc.MockRtpParameters | ||
| 20 | +import livekit.org.webrtc.RtpParameters | ||
| 19 | import livekit.org.webrtc.RtpSender | 21 | import livekit.org.webrtc.RtpSender |
| 20 | import org.mockito.Mockito | 22 | import org.mockito.Mockito |
| 23 | +import org.mockito.kotlin.any | ||
| 24 | +import org.mockito.kotlin.whenever | ||
| 25 | +import java.util.UUID | ||
| 21 | 26 | ||
| 22 | object MockRtpSender { | 27 | object MockRtpSender { |
| 23 | fun create(): RtpSender { | 28 | fun create(): RtpSender { |
| 24 | - return Mockito.mock(RtpSender::class.java) | 29 | + var rtpParameters: RtpParameters = MockRtpParameters( |
| 30 | + transactionId = UUID.randomUUID().toString(), | ||
| 31 | + degradationPreference = null, | ||
| 32 | + rtcp = MockRtpParameters.MockRtcp("", false), | ||
| 33 | + headerExtensions = mutableListOf(), | ||
| 34 | + encodings = mutableListOf(), | ||
| 35 | + codecs = mutableListOf(), | ||
| 36 | + ) | ||
| 37 | + return Mockito.mock(RtpSender::class.java).apply { | ||
| 38 | + whenever(this.parameters).thenAnswer { rtpParameters } | ||
| 39 | + whenever(this.setParameters(any())).thenAnswer { | ||
| 40 | + rtpParameters = it.getArgument(0) | ||
| 41 | + true | ||
| 42 | + } | ||
| 43 | + } | ||
| 25 | } | 44 | } |
| 26 | } | 45 | } |
| 1 | +/* | ||
| 2 | + * Copyright 2024 LiveKit, Inc. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package livekit.org.webrtc | ||
| 18 | + | ||
| 19 | +class MockRtpParameters( | ||
| 20 | + transactionId: String?, | ||
| 21 | + degradationPreference: DegradationPreference?, | ||
| 22 | + rtcp: Rtcp?, | ||
| 23 | + headerExtensions: MutableList<HeaderExtension>?, | ||
| 24 | + encodings: MutableList<Encoding>?, | ||
| 25 | + codecs: MutableList<Codec>?, | ||
| 26 | +) : RtpParameters(transactionId, degradationPreference, rtcp, headerExtensions, encodings, codecs) { | ||
| 27 | + class MockRtcp(cname: String?, reducedSize: Boolean) : Rtcp(cname, reducedSize) | ||
| 28 | + class MockHeaderExtension(uri: String?, id: Int, encrypted: Boolean) : HeaderExtension(uri, id, encrypted) | ||
| 29 | + class MockCodec(payloadType: Int, name: String?, kind: MediaStreamTrack.MediaType?, clockRate: Int?, numChannels: Int?, parameters: MutableMap<String, String>?) : | ||
| 30 | + Codec(payloadType, name, kind, clockRate, numChannels, parameters) | ||
| 31 | +} |
| @@ -40,6 +40,7 @@ import livekit.LivekitModels | @@ -40,6 +40,7 @@ import livekit.LivekitModels | ||
| 40 | import livekit.LivekitRtc | 40 | import livekit.LivekitRtc |
| 41 | import livekit.LivekitRtc.SubscribedCodec | 41 | import livekit.LivekitRtc.SubscribedCodec |
| 42 | import livekit.LivekitRtc.SubscribedQuality | 42 | import livekit.LivekitRtc.SubscribedQuality |
| 43 | +import livekit.org.webrtc.RtpParameters | ||
| 43 | import livekit.org.webrtc.VideoSource | 44 | import livekit.org.webrtc.VideoSource |
| 44 | import org.junit.Assert.* | 45 | import org.junit.Assert.* |
| 45 | import org.junit.Test | 46 | import org.junit.Test |
| @@ -333,4 +334,18 @@ class LocalParticipantMockE2ETest : MockE2ETest() { | @@ -333,4 +334,18 @@ class LocalParticipantMockE2ETest : MockE2ETest() { | ||
| 333 | }, | 334 | }, |
| 334 | ) | 335 | ) |
| 335 | } | 336 | } |
| 337 | + | ||
| 338 | + @Test | ||
| 339 | + fun publishDegradationPreferences() = runTest { | ||
| 340 | + val preference = RtpParameters.DegradationPreference.DISABLED | ||
| 341 | + room.videoTrackPublishDefaults = room.videoTrackPublishDefaults.copy(degradationPreference = preference) | ||
| 342 | + connect() | ||
| 343 | + | ||
| 344 | + room.localParticipant.publishVideoTrack(track = createLocalTrack()) | ||
| 345 | + | ||
| 346 | + val peerConnection = getPublisherPeerConnection() | ||
| 347 | + val transceiver = peerConnection.transceivers.first() | ||
| 348 | + | ||
| 349 | + assertEquals(preference, transceiver.sender.parameters.degradationPreference) | ||
| 350 | + } | ||
| 336 | } | 351 | } |
-
请 注册 或 登录 后发表评论