davidliu
Committed by GitHub

Default to software codecs for vp9 (#300)

* Default to software codecs for vp9

* Spotless
@@ -27,7 +27,8 @@ import io.livekit.android.LiveKit @@ -27,7 +27,8 @@ import io.livekit.android.LiveKit
27 import io.livekit.android.memory.CloseableManager 27 import io.livekit.android.memory.CloseableManager
28 import io.livekit.android.util.LKLog 28 import io.livekit.android.util.LKLog
29 import io.livekit.android.util.LoggingLevel 29 import io.livekit.android.util.LoggingLevel
30 -import io.livekit.android.webrtc.SimulcastVideoEncoderFactoryWrapper 30 +import io.livekit.android.webrtc.CustomVideoDecoderFactory
  31 +import io.livekit.android.webrtc.CustomVideoEncoderFactory
31 import org.webrtc.* 32 import org.webrtc.*
32 import org.webrtc.audio.AudioDeviceModule 33 import org.webrtc.audio.AudioDeviceModule
33 import org.webrtc.audio.JavaAudioDeviceModule 34 import org.webrtc.audio.JavaAudioDeviceModule
@@ -195,7 +196,7 @@ object RTCModule { @@ -195,7 +196,7 @@ object RTCModule {
195 videoEncoderFactoryOverride: VideoEncoderFactory?, 196 videoEncoderFactoryOverride: VideoEncoderFactory?,
196 ): VideoEncoderFactory { 197 ): VideoEncoderFactory {
197 return videoEncoderFactoryOverride ?: if (videoHwAccel) { 198 return videoEncoderFactoryOverride ?: if (videoHwAccel) {
198 - SimulcastVideoEncoderFactoryWrapper( 199 + CustomVideoEncoderFactory(
199 eglContext, 200 eglContext,
200 enableIntelVp8Encoder = true, 201 enableIntelVp8Encoder = true,
201 enableH264HighProfile = false, 202 enableH264HighProfile = false,
@@ -218,7 +219,7 @@ object RTCModule { @@ -218,7 +219,7 @@ object RTCModule {
218 videoDecoderFactoryOverride: VideoDecoderFactory?, 219 videoDecoderFactoryOverride: VideoDecoderFactory?,
219 ): VideoDecoderFactory { 220 ): VideoDecoderFactory {
220 return videoDecoderFactoryOverride ?: if (videoHwAccel) { 221 return videoDecoderFactoryOverride ?: if (videoHwAccel) {
221 - WrappedVideoDecoderFactory(eglContext) 222 + CustomVideoDecoderFactory(eglContext)
222 } else { 223 } else {
223 SoftwareVideoDecoderFactory() 224 SoftwareVideoDecoderFactory()
224 } 225 }
  1 +/*
  2 + * Copyright 2023 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 io.livekit.android.webrtc
  18 +
  19 +import org.webrtc.EglBase
  20 +import org.webrtc.SoftwareVideoDecoderFactory
  21 +import org.webrtc.VideoCodecInfo
  22 +import org.webrtc.VideoDecoder
  23 +import org.webrtc.VideoDecoderFactory
  24 +import org.webrtc.WrappedVideoDecoderFactory
  25 +
  26 +class CustomVideoDecoderFactory(
  27 + sharedContext: EglBase.Context?,
  28 + private var forceSWCodec: Boolean = false,
  29 + private var forceSWCodecs: List<String> = listOf("VP9"),
  30 +) : VideoDecoderFactory {
  31 + private val softwareVideoDecoderFactory = SoftwareVideoDecoderFactory()
  32 + private val wrappedVideoDecoderFactory = WrappedVideoDecoderFactory(sharedContext)
  33 +
  34 + fun setForceSWCodec(forceSWCodec: Boolean) {
  35 + this.forceSWCodec = forceSWCodec
  36 + }
  37 +
  38 + fun setForceSWCodecList(forceSWCodecs: List<String>) {
  39 + this.forceSWCodecs = forceSWCodecs
  40 + }
  41 +
  42 + override fun createDecoder(videoCodecInfo: VideoCodecInfo): VideoDecoder? {
  43 + if (forceSWCodec) {
  44 + return softwareVideoDecoderFactory.createDecoder(videoCodecInfo)
  45 + }
  46 + if (forceSWCodecs.isNotEmpty()) {
  47 + if (forceSWCodecs.contains(videoCodecInfo.name)) {
  48 + return softwareVideoDecoderFactory.createDecoder(videoCodecInfo)
  49 + }
  50 + }
  51 + return wrappedVideoDecoderFactory.createDecoder(videoCodecInfo)
  52 + }
  53 +
  54 + override fun getSupportedCodecs(): Array<VideoCodecInfo> {
  55 + return if (forceSWCodec && forceSWCodecs.isEmpty()) {
  56 + softwareVideoDecoderFactory.supportedCodecs
  57 + } else {
  58 + wrappedVideoDecoderFactory.supportedCodecs
  59 + }
  60 + }
  61 +}
  1 +/*
  2 + * Copyright 2023 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 io.livekit.android.webrtc
  18 +
  19 +import org.webrtc.EglBase
  20 +import org.webrtc.SoftwareVideoEncoderFactory
  21 +import org.webrtc.VideoCodecInfo
  22 +import org.webrtc.VideoEncoder
  23 +import org.webrtc.VideoEncoderFactory
  24 +
  25 +class CustomVideoEncoderFactory(
  26 + sharedContext: EglBase.Context?,
  27 + enableIntelVp8Encoder: Boolean,
  28 + enableH264HighProfile: Boolean,
  29 + private var forceSWCodec: Boolean = false,
  30 + private var forceSWCodecs: List<String> = listOf("VP9"),
  31 +) : VideoEncoderFactory {
  32 + private val softwareVideoEncoderFactory = SoftwareVideoEncoderFactory()
  33 + private val simulcastVideoEncoderFactoryWrapper: SimulcastVideoEncoderFactoryWrapper
  34 +
  35 + init {
  36 + simulcastVideoEncoderFactoryWrapper =
  37 + SimulcastVideoEncoderFactoryWrapper(sharedContext, enableIntelVp8Encoder, enableH264HighProfile)
  38 + }
  39 +
  40 + fun setForceSWCodec(forceSWCodec: Boolean) {
  41 + this.forceSWCodec = forceSWCodec
  42 + }
  43 +
  44 + fun setForceSWCodecList(forceSWCodecs: List<String>) {
  45 + this.forceSWCodecs = forceSWCodecs
  46 + }
  47 +
  48 + override fun createEncoder(videoCodecInfo: VideoCodecInfo): VideoEncoder? {
  49 + if (forceSWCodec) {
  50 + return softwareVideoEncoderFactory.createEncoder(videoCodecInfo)
  51 + }
  52 + if (forceSWCodecs.isNotEmpty()) {
  53 + if (forceSWCodecs.contains(videoCodecInfo.name)) {
  54 + return softwareVideoEncoderFactory.createEncoder(videoCodecInfo)
  55 + }
  56 + }
  57 + return simulcastVideoEncoderFactoryWrapper.createEncoder(videoCodecInfo)
  58 + }
  59 +
  60 + override fun getSupportedCodecs(): Array<VideoCodecInfo> {
  61 + return if (forceSWCodec && forceSWCodecs.isEmpty()) {
  62 + softwareVideoEncoderFactory.supportedCodecs
  63 + } else {
  64 + simulcastVideoEncoderFactoryWrapper.supportedCodecs
  65 + }
  66 + }
  67 +}