最近,我开始学习webrtc,并设法在我自己的信令服务器上使用一个已经存在的代码库,并且运行良好。
问题是我使用的webrtc代码仅用于视频,未实现语音传输。
由于我对webrtc不太熟悉,因此无法添加语音功能。
这是rtcclient代码(可能这是我们应该实现的语音假定权限的一部分)
class rtcclient(
context: Application,observer: PeerConnection.Observer
) {
companion object {
private const val LOCAL_TRACK_ID = "local_track"
private const val LOCAL_STREAM_ID = "local_track"
}
private val rootEglBase: EglBase = EglBase.create()
init {
initPeerConnectionFactory(context)
}
private val iceServer = listOf(
PeerConnection.IceServer.builder("stun:stun.l.google.com:19302")
.createIceServer()
)
private val peerConnectionFactory by lazy { buildPeerConnectionFactory() }
private val videoCapturer by lazy { getVideoCapturer(context) }
private val localVideoSource by lazy { peerConnectionFactory.createVideoSource(false) }
// add here something about voice ?
private val peerConnection by lazy { buildPeerConnection(observer) }
private fun initPeerConnectionFactory(context: Application) {
val options = PeerConnectionFactory.InitializationOptions.builder(context)
.setEnableInternalTracer(true)
.setfieldTrials("WebRTC-H264HighProfile/Enabled/")
.createInitializationOptions()
PeerConnectionFactory.initialize(options)
}
private fun buildPeerConnectionFactory(): PeerConnectionFactory {
return PeerConnectionFactory
.builder()
//add audio here(?)
.setVideoDecoderFactory(DefaultVideoDecoderFactory(rootEglBase.eglBaseContext))
.setVideoEncoderFactory(DefaultVideoEncoderFactory(rootEglBase.eglBaseContext,true,true))
.setOptions(PeerConnectionFactory.Options().apply {
disableEncryption = true
disableNetworkMonitor = true
})
.createPeerConnectionFactory()
}
private fun buildPeerConnection(observer: PeerConnection.Observer) = peerConnectionFactory.createPeerConnection(
iceServer,observer
)
private fun getVideoCapturer(context: Context) =
Camera2Enumerator(context).run {
deviceNames.find {
isFrontFacing(it)
}?.let {
createCapturer(it,null)
} ?: throw IllegalStateException()
}
fun initSurfaceView2(view: SurfaceViewRenderer) = view.run {
setMirror(true)
setEnableHardwareScaler(true)
init(rootEglBase.eglBaseContext,null)
}
fun initSurfaceView(view:SurfaceViewRenderer){
Log.i("surfaceview",view.toString())
view.setMirror(true)
view.setEnableHardwareScaler(true)
view?.init(rootEglBase.eglBaseContext,null)
}
fun startLocalVideoCapture(localVideoOutput: SurfaceViewRenderer) {
// implement voice transfer here (?)
val surfaceTextureHelper = SurfaceTextureHelper.create(Thread.currentThread().name,rootEglBase.eglBaseContext)
(videoCapturer as VideoCapturer).initialize(surfaceTextureHelper,localVideoOutput.context,localVideoSource.capturerObserver)
videoCapturer.startCapture(320,240,60)
val localVideoTrack = peerConnectionFactory.createVideoTrack(LOCAL_TRACK_ID,localVideoSource)
localVideoTrack.addSink(localVideoOutput)
val localStream = peerConnectionFactory.createLocalMediaStream(LOCAL_STREAM_ID)
localStream.addTrack(localVideoTrack)
peerConnection?.addStream(localStream)
}
private fun PeerConnection.call(sdpObserver: SdpObserver) {
val constraints = MediaConstraints().apply {
mandatory.add(MediaConstraints.keyvaluepair("OfferToReceiveVideo","true"))
}
createOffer(object : SdpObserver by sdpObserver {
override fun onCreateSuccess(desc: SessionDescription?) {
setLocalDescription(object : SdpObserver {
override fun onsetfailure(p0: String?) {
}
override fun onSetSuccess() {
}
override fun onCreateSuccess(p0: SessionDescription?) {
}
override fun onCreateFailure(p0: String?) {
}
},desc)
sdpObserver.onCreateSuccess(desc)
}
},constraints)
}
private fun PeerConnection.answer(sdpObserver: SdpObserver) {
val constraints = MediaConstraints().apply {
mandatory.add(MediaConstraints.keyvaluepair("OfferToReceiveVideo","true"))
}
createAnswer(object : SdpObserver by sdpObserver {
override fun onCreateSuccess(p0: SessionDescription?) {
setLocalDescription(object : SdpObserver {
override fun onsetfailure(p0: String?) {
}
override fun onSetSuccess() {
}
override fun onCreateSuccess(p0: SessionDescription?) {
}
override fun onCreateFailure(p0: String?) {
}
},p0)
sdpObserver.onCreateSuccess(p0)
}
},constraints)
}
fun call(sdpObserver: SdpObserver) = peerConnection?.call(sdpObserver)
fun answer(sdpObserver: SdpObserver) = peerConnection?.answer(sdpObserver)
fun onRemoteSessionReceived(sessionDescription: SessionDescription) {
peerConnection?.setRemoteDescription(object : SdpObserver {
override fun onsetfailure(p0: String?) {
}
override fun onSetSuccess() {
}
override fun onCreateSuccess(p0: SessionDescription?) {
}
override fun onCreateFailure(p0: String?) {
}
},sessionDescription)
}
fun addIceCandidate(iceCandidate: IceCandidate?) {
peerConnection?.addIceCandidate(iceCandidate)
}
}