我正在尝试使用WebRTC Native Code package for Android(即不使用WebView)在Android应用程序中实现三向视频聊天。我已经使用node.js编写了一个信令服务器,并使用客户端应用程序中的Gottox socket.io java client库连接到服务器,交换SDP数据包并建立2路视频聊天连接。

但是,现在我遇到了无法进行三通通话的问题。 WebRTC native 代码包随附的AppRTCDemo应用程序仅演示双向 call (如果第三方尝试加入 session 室,则会返回“room full”消息)。

根据this answer(与Android无关),我应该通过创建多个PeerConnections来做到这一点,因此每个聊天参与者都将连接到其他2个参与者。

但是,当我创建多个PeerConnectionClient(包装PeerConection的Java类,该类在libjingle_peerconnection_so.so的 native 端实现)时,库内部会引发异常,这是因为它们都试图冲突存取相机:

E/VideoCapturerAndroid(21170): startCapture failed
E/VideoCapturerAndroid(21170): java.lang.RuntimeException: Fail to connect to camera service
E/VideoCapturerAndroid(21170):  at android.hardware.Camera.native_setup(Native Method)
E/VideoCapturerAndroid(21170):  at android.hardware.Camera.<init>(Camera.java:548)
E/VideoCapturerAndroid(21170):  at android.hardware.Camera.open(Camera.java:389)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid.startCaptureOnCameraThread(VideoCapturerAndroid.java:528)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid.access$11(VideoCapturerAndroid.java:520)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid$6.run(VideoCapturerAndroid.java:514)
E/VideoCapturerAndroid(21170):  at android.os.Handler.handleCallback(Handler.java:733)
E/VideoCapturerAndroid(21170):  at android.os.Handler.dispatchMessage(Handler.java:95)
E/VideoCapturerAndroid(21170):  at android.os.Looper.loop(Looper.java:136)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid$CameraThread.run(VideoCapturerAndroid.java:484)

即使在尝试建立连接之前初始化本地客户端时,也会发生这种情况,因此它与node.js,socket.io或任何信令服务器无关。

如何获得多个PeerConnections共享摄像机,以便可以将同一视频发送给多个同伴?

我曾经有一个想法是实现某种单例相机类来代替可以在多个连接之间共享的VideoCapturerAndroid,但是我什至不确定那是否可行,我想知道是否有一种方法可以做到3-在开始在库中进行黑客入侵之前,请使用API​​进行方式调用。

有可能吗?

更新:

我尝试在多个PeerConnectionClients之间共享VideoCapturerAndroid对象,仅为第一个连接创建该对象,然后将其传递给后续连接的初始化函数,但这导致此“Capturer只能使用一次!”从VideoCapturer对象为第二个对等连接创建第二个VideoTrack时出现异常:
E/AndroidRuntime(18956): FATAL EXCEPTION: Thread-1397
E/AndroidRuntime(18956): java.lang.RuntimeException: Capturer can only be taken once!
E/AndroidRuntime(18956):    at org.webrtc.VideoCapturer.takeNativeVideoCapturer(VideoCapturer.java:52)
E/AndroidRuntime(18956):    at org.webrtc.PeerConnectionFactory.createVideoSource(PeerConnectionFactory.java:113)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient.createVideoTrack(PeerConnectionClient.java:720)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient.createPeerConnectionInternal(PeerConnectionClient.java:482)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient.access$20(PeerConnectionClient.java:433)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient$2.run(PeerConnectionClient.java:280)
E/AndroidRuntime(18956):    at android.os.Handler.handleCallback(Handler.java:733)
E/AndroidRuntime(18956):    at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime(18956):    at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime(18956):    at com.example.rtcapp.LooperExecutor.run(LooperExecutor.java:56)

尝试在PeerConnectionClients之间共享VideoTrack对象会导致 native 代码出现此错误:
E/libjingle(19884): Local fingerprint does not match identity.
E/libjingle(19884): P2PTransportChannel::Connect: The ice_ufrag_ and the ice_pwd_ are not set.
E/libjingle(19884): Local fingerprint does not match identity.
E/libjingle(19884): Failed to set local offer sdp: Failed to push down transport description: Local fingerprint does not match identity.

在PeerConnectionClients之间共享MediaStream会导致应用突然关闭,而Logcat中不会出现任何错误消息。

最佳答案

您遇到的问题是PeerConnectionClient是,而不是,它是PeerConnection的包装,它包含是PeerConnection。

我注意到这个问题没有得到回答,所以我想看看能否帮上忙。我查看了源代码,PeerConnectionClient对单个远程对等方进行了非常硬的编码。您将需要创建PeerConnection对象的集合,而不是下面的代码行:

private PeerConnection peerConnection;

如果环顾四周,您会发现它变得更复杂了。

createPeerConnectionInternal中的mediaStream逻辑仅应执行一次,并且您需要像这样在PeerConnection对象之间共享流:
peerConnection.addStream(mediaStream);

您可以查询WebRTC spec或查看这个stackoverflow问题,以确认PeerConnection类型设计为仅处理一个对等体。在某种程度上也隐含了here

因此,您只需维护一个mediaStream对象:
private MediaStream mediaStream;

因此,主要思想还是一个MediaStream对象和与要连接的对等体一样多的PeerConnection对象。因此,您将不会使用多个PeerConnectionClient对象,而是修改单个PeerConnectionClient来封装多客户端处理。如果您出于某种原因想要设计多个PeerConnectionClient对象,则只需从其中抽象出媒体流逻辑(以及任何只能创建一次的支持类型)。

您还需要维护多个远程视频轨道,而不是现有的一个:
private VideoTrack remoteVideoTrack;

显然,您只关心渲染一台本地摄像机并为远程连接创建多个渲染器。

我希望这些信息足以使您重回正轨。

08-26 10:07