正在显示
4 个修改的文件
包含
127 行增加
和
15 行删除
| @@ -3,7 +3,11 @@ package io.livekit.android.room.track | @@ -3,7 +3,11 @@ package io.livekit.android.room.track | ||
| 3 | import android.Manifest | 3 | import android.Manifest |
| 4 | import android.content.Context | 4 | import android.content.Context |
| 5 | import android.content.pm.PackageManager | 5 | import android.content.pm.PackageManager |
| 6 | +import android.hardware.camera2.CameraManager | ||
| 6 | import androidx.core.content.ContextCompat | 7 | import androidx.core.content.ContextCompat |
| 8 | +import io.livekit.android.room.track.video.Camera1CapturerWithSize | ||
| 9 | +import io.livekit.android.room.track.video.Camera2CapturerWithSize | ||
| 10 | +import io.livekit.android.room.track.video.VideoCapturerWithSize | ||
| 7 | import io.livekit.android.util.LKLog | 11 | import io.livekit.android.util.LKLog |
| 8 | import org.webrtc.* | 12 | import org.webrtc.* |
| 9 | import java.util.* | 13 | import java.util.* |
| @@ -28,14 +32,17 @@ open class LocalVideoTrack( | @@ -28,14 +32,17 @@ open class LocalVideoTrack( | ||
| 28 | override var rtcTrack: org.webrtc.VideoTrack = rtcTrack | 32 | override var rtcTrack: org.webrtc.VideoTrack = rtcTrack |
| 29 | internal set | 33 | internal set |
| 30 | 34 | ||
| 31 | - /** | ||
| 32 | - * Note: these dimensions are only requested params, and may differ | ||
| 33 | - * from the actual capture format used by the camera. | ||
| 34 | - * | ||
| 35 | - * TODO: capture actual dimensions used | ||
| 36 | - */ | ||
| 37 | val dimensions: Dimensions | 35 | val dimensions: Dimensions |
| 38 | - get() = Dimensions(options.captureParams.width, options.captureParams.height) | 36 | + get() { |
| 37 | + (capturer as? VideoCapturerWithSize)?.let { capturerWithSize -> | ||
| 38 | + val size = capturerWithSize.findCaptureFormat( | ||
| 39 | + options.captureParams.width, | ||
| 40 | + options.captureParams.height | ||
| 41 | + ) | ||
| 42 | + return Dimensions(size.width, size.height) | ||
| 43 | + } | ||
| 44 | + return Dimensions(options.captureParams.width, options.captureParams.height) | ||
| 45 | + } | ||
| 39 | 46 | ||
| 40 | internal var transceiver: RtpTransceiver? = null | 47 | internal var transceiver: RtpTransceiver? = null |
| 41 | private val sender: RtpSender? | 48 | private val sender: RtpSender? |
| @@ -127,9 +134,9 @@ open class LocalVideoTrack( | @@ -127,9 +134,9 @@ open class LocalVideoTrack( | ||
| 127 | 134 | ||
| 128 | private fun createVideoCapturer(context: Context, position: CameraPosition): VideoCapturer? { | 135 | private fun createVideoCapturer(context: Context, position: CameraPosition): VideoCapturer? { |
| 129 | val videoCapturer: VideoCapturer? = if (Camera2Enumerator.isSupported(context)) { | 136 | val videoCapturer: VideoCapturer? = if (Camera2Enumerator.isSupported(context)) { |
| 130 | - createCameraCapturer(Camera2Enumerator(context), position) | 137 | + createCameraCapturer(context, Camera2Enumerator(context), position) |
| 131 | } else { | 138 | } else { |
| 132 | - createCameraCapturer(Camera1Enumerator(true), position) | 139 | + createCameraCapturer(context, Camera1Enumerator(true), position) |
| 133 | } | 140 | } |
| 134 | if (videoCapturer == null) { | 141 | if (videoCapturer == null) { |
| 135 | LKLog.d { "Failed to open camera" } | 142 | LKLog.d { "Failed to open camera" } |
| @@ -138,26 +145,47 @@ open class LocalVideoTrack( | @@ -138,26 +145,47 @@ open class LocalVideoTrack( | ||
| 138 | return videoCapturer | 145 | return videoCapturer |
| 139 | } | 146 | } |
| 140 | 147 | ||
| 141 | - private fun createCameraCapturer(enumerator: CameraEnumerator, position: CameraPosition): VideoCapturer? { | 148 | + private fun createCameraCapturer( |
| 149 | + context: Context, | ||
| 150 | + enumerator: CameraEnumerator, | ||
| 151 | + position: CameraPosition | ||
| 152 | + ): VideoCapturer? { | ||
| 142 | val deviceNames = enumerator.deviceNames | 153 | val deviceNames = enumerator.deviceNames |
| 143 | - | 154 | + var targetDeviceName: String? = null |
| 155 | + var targetVideoCapturer: VideoCapturer? = null | ||
| 144 | for (deviceName in deviceNames) { | 156 | for (deviceName in deviceNames) { |
| 145 | if (enumerator.isFrontFacing(deviceName) && position == CameraPosition.FRONT) { | 157 | if (enumerator.isFrontFacing(deviceName) && position == CameraPosition.FRONT) { |
| 146 | LKLog.v { "Creating front facing camera capturer." } | 158 | LKLog.v { "Creating front facing camera capturer." } |
| 147 | val videoCapturer = enumerator.createCapturer(deviceName, null) | 159 | val videoCapturer = enumerator.createCapturer(deviceName, null) |
| 148 | if (videoCapturer != null) { | 160 | if (videoCapturer != null) { |
| 149 | - return videoCapturer | 161 | + targetDeviceName = deviceName |
| 162 | + targetVideoCapturer = videoCapturer | ||
| 163 | + break | ||
| 150 | } | 164 | } |
| 151 | } else if (enumerator.isBackFacing(deviceName) && position == CameraPosition.BACK) { | 165 | } else if (enumerator.isBackFacing(deviceName) && position == CameraPosition.BACK) { |
| 152 | LKLog.v { "Creating back facing camera capturer." } | 166 | LKLog.v { "Creating back facing camera capturer." } |
| 153 | val videoCapturer = enumerator.createCapturer(deviceName, null) | 167 | val videoCapturer = enumerator.createCapturer(deviceName, null) |
| 154 | if (videoCapturer != null) { | 168 | if (videoCapturer != null) { |
| 155 | - return videoCapturer | 169 | + targetDeviceName = deviceName |
| 170 | + targetVideoCapturer = videoCapturer | ||
| 171 | + break | ||
| 156 | } | 172 | } |
| 157 | } | 173 | } |
| 158 | } | 174 | } |
| 175 | + | ||
| 176 | + if (targetVideoCapturer is Camera1Capturer) { | ||
| 177 | + return Camera1CapturerWithSize(targetVideoCapturer, targetDeviceName) | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + if (targetVideoCapturer is Camera2Capturer) { | ||
| 181 | + return Camera2CapturerWithSize( | ||
| 182 | + targetVideoCapturer, | ||
| 183 | + context.getSystemService(Context.CAMERA_SERVICE) as CameraManager, | ||
| 184 | + targetDeviceName | ||
| 185 | + ) | ||
| 186 | + } | ||
| 187 | + | ||
| 159 | return null | 188 | return null |
| 160 | } | 189 | } |
| 161 | - | ||
| 162 | } | 190 | } |
| 163 | -} | ||
| 191 | +} |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/video/VideoCapturerWithSize.kt
0 → 100644
| 1 | +package io.livekit.android.room.track.video | ||
| 2 | + | ||
| 3 | +import android.hardware.camera2.CameraManager | ||
| 4 | +import org.webrtc.* | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * @suppress | ||
| 8 | + */ | ||
| 9 | +internal interface VideoCapturerWithSize : VideoCapturer { | ||
| 10 | + fun findCaptureFormat(width: Int, height: Int): Size | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * @suppress | ||
| 15 | + */ | ||
| 16 | +internal class Camera1CapturerWithSize( | ||
| 17 | + private val capturer: Camera1Capturer, | ||
| 18 | + private val deviceName: String? | ||
| 19 | +) : VideoCapturer by capturer, VideoCapturerWithSize { | ||
| 20 | + override fun findCaptureFormat(width: Int, height: Int): Size { | ||
| 21 | + val cameraId = Camera1Helper.getCameraId(deviceName) | ||
| 22 | + return Camera1Helper.findClosestCaptureFormat(cameraId, width, height) | ||
| 23 | + } | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * @suppress | ||
| 28 | + */ | ||
| 29 | +internal class Camera2CapturerWithSize( | ||
| 30 | + private val capturer: Camera2Capturer, | ||
| 31 | + private val cameraManager: CameraManager, | ||
| 32 | + private val deviceName: String? | ||
| 33 | +) : VideoCapturer by capturer, VideoCapturerWithSize { | ||
| 34 | + override fun findCaptureFormat(width: Int, height: Int): Size { | ||
| 35 | + return Camera2Helper.findClosestCaptureFormat(cameraManager, deviceName, width, height) | ||
| 36 | + } | ||
| 37 | +} |
| 1 | +package org.webrtc | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * A helper to access package-protected methods used in [Camera2Session] | ||
| 5 | + * @suppress | ||
| 6 | + */ | ||
| 7 | +internal class Camera1Helper { | ||
| 8 | + companion object { | ||
| 9 | + fun getCameraId(deviceName: String?) = Camera1Enumerator.getCameraIndex(deviceName) | ||
| 10 | + | ||
| 11 | + fun findClosestCaptureFormat( | ||
| 12 | + cameraId: Int, | ||
| 13 | + width: Int, | ||
| 14 | + height: Int | ||
| 15 | + ): Size { | ||
| 16 | + return CameraEnumerationAndroid.getClosestSupportedSize( | ||
| 17 | + Camera1Enumerator.getSupportedFormats(cameraId) | ||
| 18 | + .map { Size(it.width, it.height) }, | ||
| 19 | + width, | ||
| 20 | + height | ||
| 21 | + ) | ||
| 22 | + } | ||
| 23 | + } | ||
| 24 | +} |
| 1 | +package org.webrtc | ||
| 2 | + | ||
| 3 | +import android.hardware.camera2.CameraManager | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * A helper to access package-protected methods used in [Camera2Session] | ||
| 7 | + * @suppress | ||
| 8 | + */ | ||
| 9 | +internal class Camera2Helper { | ||
| 10 | + companion object { | ||
| 11 | + fun findClosestCaptureFormat( | ||
| 12 | + cameraManager: CameraManager, | ||
| 13 | + cameraId: String?, | ||
| 14 | + width: Int, | ||
| 15 | + height: Int | ||
| 16 | + ): Size { | ||
| 17 | + val sizes = Camera2Enumerator.getSupportedFormats(cameraManager, cameraId) | ||
| 18 | + ?.map { Size(it.width, it.height) } | ||
| 19 | + ?: emptyList() | ||
| 20 | + return CameraEnumerationAndroid.getClosestSupportedSize(sizes, width, height) | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | +} |
-
请 注册 或 登录 后发表评论