相機預覽 WebRTC

      在〈相機預覽 WebRTC〉中尚無留言

開始撰寫 init()、createAudioConstraints() 及 createVideoCapture() 就可以開始預覽相機

啟動相機完整代碼

底下程式碼可以正確啟動相機

import android.content.Context
import android.media.MediaCodecInfo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import net.ddns.mahaljsp.cameraw.databinding.ActivityMainBinding
import org.webrtc.AudioTrack
import org.webrtc.Camera1Enumerator
import org.webrtc.Camera2Enumerator
import org.webrtc.CameraEnumerator
import org.webrtc.CameraVideoCapturer
import org.webrtc.DefaultVideoDecoderFactory
import org.webrtc.EglBase
import org.webrtc.MediaConstraints
import org.webrtc.PeerConnection
import org.webrtc.PeerConnectionFactory
import org.webrtc.RendererCommon
import org.webrtc.SurfaceTextureHelper
import org.webrtc.VideoEncoderSupportedCallback
import org.webrtc.VideoTrack
import org.webrtc.createCustomVideoEncoderFactory

class MainActivity : AppCompatActivity() {
    lateinit var permission:MainPermission
    lateinit var ui:ActivityMainBinding
    lateinit var rtcConfig : PeerConnection.RTCConfiguration
    var surfaceTextureHelper: SurfaceTextureHelper? = null
    var videoTrack: VideoTrack? = null
    var audioTrack: AudioTrack? = null
    val eglBaseContext = EglBase.create().eglBaseContext
    lateinit var peerConnectionFactory: PeerConnectionFactory
    fun init(){
        ui.localView.init(eglBaseContext, null)
        ui.localView.setEnableHardwareScaler(true)
        ui.localView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
        ui.localView.setZOrderMediaOverlay(true);
        PeerConnectionFactory.initialize(
            PeerConnectionFactory.InitializationOptions
                .builder(this).createInitializationOptions()
        )
        val options = PeerConnectionFactory.Options()
        val encoderFactory = createCustomVideoEncoderFactory(
            eglBaseContext,true,true,
            object : VideoEncoderSupportedCallback {
                override fun isSupportedVp8(info: MediaCodecInfo): Boolean {
                    return true
                }
                override fun isSupportedVp9(info: MediaCodecInfo): Boolean {
                    return true
                }
                override fun isSupportedH264(info: MediaCodecInfo): Boolean {
                    return true
                }
            })
        val decoderFactory = DefaultVideoDecoderFactory(eglBaseContext)
        peerConnectionFactory = PeerConnectionFactory.builder()
            .setOptions(options)
            .setVideoEncoderFactory(encoderFactory)
            .setVideoDecoderFactory(decoderFactory)
            .createPeerConnectionFactory()
        val audioSource = peerConnectionFactory.createAudioSource(
            createAudioConstraints()
        )
        audioTrack = peerConnectionFactory.createAudioTrack(
            "local_audio_track",
            audioSource
        )
        val videoCapture = createVideoCapture(this)
        val videoSource = peerConnectionFactory.createVideoSource(
            videoCapture!!.isScreencast
        )
        videoTrack =peerConnectionFactory.createVideoTrack(
            "local_video_track",
            videoSource
        )
        surfaceTextureHelper = SurfaceTextureHelper.create(
            "surface_thread", eglBaseContext
        )
        
        //第二個參數為 this,也可以是getApplicationContext()
        videoCapture?.initialize(
            surfaceTextureHelper, 
            this, 
            videoSource.capturerObserver
        )
        videoTrack?.addSink(ui.localView)
        videoCapture?.startCapture(1920, 1080, 25)
        rtcConfig = PeerConnection.RTCConfiguration(emptyList())
        rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN
    }

    private fun createAudioConstraints(): MediaConstraints {
        val audioConstraints = MediaConstraints()
        //消除回音
        audioConstraints.mandatory.add(
            MediaConstraints.KeyValuePair(
                "googEchoCancellation",
                "true"
            )
        )
        //自動增益 Automatic Gain Control(AGC) 聲音輸入時有時大,有時小。
        // 自動增益會依輸入的音量自動增減,讓輸出時保持固定音量
        audioConstraints.mandatory.add(MediaConstraints.KeyValuePair(
            "googAutoGainControl", "true")
        )
        //高音過濾
        audioConstraints.mandatory.add(MediaConstraints.KeyValuePair(
            "googHighpassFilter", "true")
        )
        //降噪
        audioConstraints.mandatory.add(
            MediaConstraints.KeyValuePair(
                "googNoiseSuppression",
                "true"
            )
        )
        return audioConstraints
    }

    private fun createVideoCapture(context: Context): CameraVideoCapturer? {
        val enumerator: CameraEnumerator = if (Camera2Enumerator.isSupported(context)) {
            Camera2Enumerator(context)
        } else {
            Camera1Enumerator()
        }
        for (name in enumerator.deviceNames) {
            if (enumerator.isBackFacing(name)) {
                return enumerator.createCapturer(name, null)
            }
        }
        for (name in enumerator.deviceNames) {
            if (enumerator.isBackFacing(name)) {
                return enumerator.createCapturer(name, null)
            }
        }
        return null
    }

todo

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *