原文链接:WebRTC之Android客户端

六、回调函数

1.WebSocket回调接口与主要消息处理

Candidate、answer、offer、bye四大类消息

private class WebSocketObserverimplements WebSocketConnectionObserver {    @Override    public void onOpen() {      Log.d(TAG, "WebSocket connection opened to: " + wsServerUrl);      executor.execute(new Runnable() {        @Override        public void run() {          state = WebSocketConnectionState.CONNECTED;          // Check if we have pending register request.          if (roomID !=null && clientID != null) {            register(roomID, clientID);          }        }      });    }     @Override    public void onClose(WebSocketCloseNotification code, String reason) {      Log.d(TAG, "WebSocket connection closed. Code: " + code          + ". Reason: " + reason + ". State: " + state);      synchronized (closeEventLock) {        closeEvent = true;        closeEventLock.notify();      }      executor.execute(new Runnable() {        @Override        public void run() {          if (state != WebSocketConnectionState.CLOSED) {            state = WebSocketConnectionState.CLOSED;            events.onWebSocketClose();          }        }      });    }     @Override    public void onTextMessage(String payload) {      Log.d(TAG, "WSS->C: " + payload);      final String message = payload;      executor.execute(new Runnable() {        @Override        public void run() {          if (state == WebSocketConnectionState.CONNECTED              || state == WebSocketConnectionState.REGISTERED) {            events.onWebSocketMessage(message);          }        }      });    }     @Override    public void onRawTextMessage(byte[] payload) {    }     @Override    public void onBinaryMessage(byte[] payload) {    }  } @Override  public void onWebSocketMessage(final String msg) {    if (wsClient.getState() != WebSocketConnectionState.REGISTERED) {      Log.e(TAG, "Got WebSocket message in non registered state.");      return;    }    try {      JSONObject json = new JSONObject(msg);      String msgText = json.getString("msg");      String errorText = json.optString("error");      if (msgText.length() > 0) {        json = new JSONObject(msgText);        String type = json.optString("type");        if (type.equals("candidate")) {          IceCandidate candidate = new IceCandidate(              json.getString("id"),              json.getInt("label"),              json.getString("candidate"));          events.onRemoteIceCandidate(candidate);        } else if (type.equals("answer")) {          if (initiator) {            SessionDescription sdp = new SessionDescription(                SessionDescription.Type.fromCanonicalForm(type),                json.getString("sdp"));            events.onRemoteDescription(sdp);          } else {            reportError("Received answer for call initiator: " + msg);          }        } else if (type.equals("offer")) {          if (!initiator) {            SessionDescription sdp = new SessionDescription(                SessionDescription.Type.fromCanonicalForm(type),                json.getString("sdp"));            events.onRemoteDescription(sdp);          } else {            reportError("Received offer for call receiver: " + msg);          }        } else if (type.equals("bye")) {          events.onChannelClose();        } else {          reportError("Unexpected WebSocket message: " + msg);        }      } else {        if (errorText !=null && errorText.length() > 0) {          reportError("WebSocket error message: " + errorText);        } else {          reportError("Unexpected WebSocket message: " + msg);        }      }    } catch (JSONException e) {      reportError("WebSocket message JSON parsing error: " + e.toString());    }  }

2.Observer接口

主要是连接建立完成后Ice的改变和流信息的改变引起的回调

public static interface Observer {    /** Triggered when the SignalingState changes. */    public void onSignalingChange(SignalingState newState);     /** Triggered when the IceConnectionState changes. */    public void onIceConnectionChange(IceConnectionState newState);     /** Triggered when the ICE connection receiving status changes. */    public void onIceConnectionReceivingChange(boolean receiving);     /** Triggered when the IceGatheringState changes. */    public void onIceGatheringChange(IceGatheringState newState);     /** Triggered when a new ICE candidate has been found. */    public void onIceCandidate(IceCandidate candidate);     /** Triggered when media is received on a new stream from remote peer. */    public void onAddStream(MediaStream stream);     /** Triggered when a remote peer close a stream. */    public void onRemoveStream(MediaStream stream);     /** Triggered when a remote peer opens a DataChannel. */    public void onDataChannel(DataChannel dataChannel);     /** Triggered when renegotiation is necessary. */    public void onRenegotiationNeeded();  }

3.SDP接口

主要是连接建立的过程中引起的回调

/** Interface for observing SDP-related events. */public interface SdpObserver {  /** Called on success of Create{Offer,Answer}(). */  public void onCreateSuccess(SessionDescription sdp);   /** Called on success of Set{Local,Remote}Description(). */  public void onSetSuccess();   /** Called on error of Create{Offer,Answer}(). */  public void onCreateFailure(String error);   /** Called on error of Set{Local,Remote}Description(). */  public void onSetFailure(String error);}

4.PeerConnectionClient

生成PeerConnection,实现相关的回调,完成整个业务逻辑private final PCObserverpcObserver = new PCObserver();(Observer )private final SDPObserversdpObserver = new SDPObserver();(SdpObserver)private PeerConnectionFactoryfactory;private PeerConnectionpeerConnection;

5.CallActivity

private PeerConnectionClientpeerConnectionClient = null;private AppRTCClientappRtcClient;

七、Native函数之信令协商

6.1 加载so文件

static {    System.loadLibrary("jingle_peerconnection_so");  }

6.2 PeerConnectionFactory相关Native函数
6.2.1网络接口相关参数

public static class Options {    // Keep in sync with webrtc/base/network.h!    static final int ADAPTER_TYPE_UNKNOWN = 0;    static final int ADAPTER_TYPE_ETHERNET = 1 << 0;    static final int ADAPTER_TYPE_WIFI = 1 << 1;    static final int ADAPTER_TYPE_CELLULAR = 1 << 2;    static final int ADAPTER_TYPE_VPN = 1 << 3;    static final int ADAPTER_TYPE_LOOPBACK = 1 << 4;    public int networkIgnoreMask;    public boolean disableEncryption;  }

6.2.2初始化PeerConnectionFactory

// |context| is an android.content.Context object, but we keep it untyped here  // to allow building on non-Android platforms.  // Callers may specify either |initializeAudio| or |initializeVideo| as false  // to skip initializing the respective engine (and avoid the need for the  // respective permissions).  // |renderEGLContext| can be provided to suport HW video decoding to  // texture and will be used to create a shared EGL context on video  // decoding thread.public static native boolean initializeAndroidGlobals(Object context, boolean initializeAudio, boolean initializeVideo,boolean videoHwAcceleration);Context:简单的ApplicationContext,或者其他Context相关的上下文。initializeAudio:初始化音频部分。(boolean)videoHwAcceleration:是否启用硬件加速。(boolean

6.2.3初始化音视频轨

private static final String FIELD_TRIAL_VP9 = "WebRTC-SupportVP9/Enabled/";// Field trial initialization. Must be called before PeerConnectionFactory  // is created.public static native void initializeFieldTrials(String fieldTrialsInitString);

6.2.4 PeerConnectionFactory其他函数

//创建Factoryprivate static native long nativeCreatePeerConnectionFactory();//创建指令回调接口(与ICE服务器进行交互的指令)private static native long nativeCreateObserver(PeerConnection.Observer observer);//创建PeerConnectionprivate static native long nativeCreatePeerConnection(long nativeFactory, PeerConnection.RTCConfiguration rtcConfig, ediaConstraints constraints, long nativeObserver);//创建本地音视频流private static native long nativeCreateLocalMediaStream(long nativeFactory, String label);//创建本地视频源private static native long nativeCreateVideoSource(long nativeFactory, long nativeVideoCapturer,  MediaConstraints constraints);//创建视频轨private static native long nativeCreateVideoTrack(long nativeFactory, String id, long nativeVideoSource);//创建本地音频流private static native long nativeCreateAudioSource(long nativeFactory, MediaConstraints constraints);//创建音频轨private static native long nativeCreateAudioTrack(long nativeFactory, String id, long nativeSource);//设置相关网络参数public native void nativeSetOptions(long nativeFactory, Options options);//设置视频硬件加速参数private static native void nativeSetVideoHwAccelerationOptions(long nativeFactory, Object renderEGLContext);//回收PeerConnectionFactoryprivate static native void freeFactory(long nativeFactory);

6.3 PeerConnection相关Native函数

6.3.1相关信令状态

//检测本地candidate的状态:刚刚创建、正在收集、完成收集** Tracks PeerConnectionInterface::IceGatheringState */  public enum IceGatheringState { NEW, GATHERING, COMPLETE }; //检测远端candidate的状态  /** Tracks PeerConnectionInterface::IceConnectionState */  public enum IceConnectionState {    NEW, CHECKING, CONNECTED, COMPLETED, FAILED, DISCONNECTED, CLOSED  }; //检测与Sigal信令服务器连接的状态  /** Tracks PeerConnectionInterface::SignalingState */  public enum SignalingState {    STABLE, HAVE_LOCAL_OFFER, HAVE_LOCAL_PRANSWER, HAVE_REMOTE_OFFER,    HAVE_REMOTE_PRANSWER, CLOSED  };

6.3.2 Native函数介绍

//得到本地sdp描述public native SessionDescription getLocalDescription();//得到远端sdp描述public native SessionDescription getRemoteDescription();//创建数据通道public native DataChannel createDataChannel(String label, DataChannel.Init init);//创建offer消息public native void createOffer(SdpObserver observer, MediaConstraints constraints);//创建answer消息public native void createAnswer(SdpObserver observer, MediaConstraints constraints);//设置本地sdppublic native void setLocalDescription(SdpObserver observer, SessionDescription sdp);//设置远端sdppublic native void setRemoteDescription(SdpObserver observer, SessionDescription sdp);//更新IceServerpublic native boolean updateIce(List<IceServer> iceServers, MediaConstraints constraints);//得到信令状态public native SignalingState signalingState(); //获得远端连接状态public native IceConnectionState iceConnectionState();//获得本地连接状态public native IceGatheringState iceGatheringState();//关闭与Ice服务器的连接public native void close();//释放PeerConnectionprivate static native void freePeerConnection(long nativePeerConnection);//释放Observerprivate static native void freeObserver(long nativeObserver);//添加新的Candidateprivate native boolean nativeAddIceCandidate(String sdpMid, int sdpMLineIndex, String iceCandidateSdp);//添加本地流private native boolean nativeAddLocalStream(long nativeStream);//移除本地流private native void nativeRemoveLocalStream(long nativeStream);//得到StatsObserver的状态private native boolean nativeGetStats(StatsObserver observer, long nativeTrack);

八、Native函数之音视频

一旦有了peerConnectionFactory实例,就应该从你的设备上获取音频和视频了,最终渲染到屏幕上。VideoCapturerAndroid,VideoSource,VideoTrack和VideoRenderer,都是以VideoCapturerAndroid开始。

8.1 VideoCapturerAndroid
VideoCapturerAndroid类是一个相机的包装类,提供访问设备相机数据流的江边方法。允许你获取设备数量,获取前置后置摄像头

// Returns the number of camera devicesVideoCapturerAndroid.getDeviceCount();// Returns the front face device nameVideoCapturerAndroid.getNameOfFrontFacingDevice();// Returns the back facing device nameVideoCapturerAndroid.getNameOfBackFacingDevice(); // Creates a VideoCapturerAndroid instance for the device nameVideoCapturerAndroid.create(name);

使用VideoCapturerAndroid类的实例,可以创建包含相机视频流的MediaStream,你可以给对方发送数据。

8.2 VideoSource/VideoTrack
VideoSource可以开始或停止你的设备。在无用停止抓取信息有助于电池使用寿命的延长。

VideoTrack是一个添加VideoSource到MediaStream对象的一个包装。

8.3 AudioSource/AudioTrack
除了不需要AudioCapturer获取麦克风数据,AudioSource/AudioTrack和VideoSource/VideoTrack很类似。audioConstraints是MediaContraints的实例。

8.4 VideoRenderer
VideoRendererGui是一个GLSurfaceView,在这之上,可以显示视频流,增加我们的renderer到VideoTrack上。

// To create our VideoRenderer, we can use the// included VideoRendererGui for simplicity// First we need to set the GLSurfaceView that it should render toGLSurfaceView videoView = (GLSurfaceView) findViewById(R.id.glview_call);// Then we set that view, and pass a Runnable// to run once the surface is readyVideoRendererGui.setView(videoView, runnable);// Now that VideoRendererGui is ready, we can get our VideoRendererVideoRenderer renderer = VideoRendererGui.createGui(x, y, width, height);// And finally, with our VideoRenderer ready, we// can add our renderer to the VideoTrack.localVideoTrack.addRenderer(renderer);

8.5 MediaConstraints
这个MediaConstraints是WebRTC支持将视频和音频放入MediaStream的方式。看这个支持的规范,大多数方法都需要MediaContraints的实例。

8.6 MediaStream
getUserMedia直接返回一个MediaStream,可以直接将其添加到RTCPeerConnection中发送给对端。

// We start out with an empty MediaStream object,// created with help from our PeerConnectionFactory// Note that LOCAL_MEDIA_STREAM_ID can be any stringMediaStream mediaStream = peerConnectionFactory.createLocalMediaStream(LOCAL_MEDIA_STREAM_ID); // Now we can add our tracks.mediaStream.addTrack(localVideoTrack);mediaStream.addTrack(localAudioTrack);

更多相关文章

  1. C语言函数以及函数的使用
  2. android中去掉空格--trim函数
  3. Android使用videoview播放res/raw下的视频
  4. Android视频开发国人开发的Vitamio开源项目
  5. Android Q : 安卓源码、水滴屏适配状态栏图标(图标过多时显示一个
  6. android 动态控制状态栏显示和隐藏的方法实例
  7. android状态栏一体化(沉浸式状态栏)
  8. 移动端H5的Video标签无法播放在线视频的问题

随机推荐

  1. 21个新奇漂亮的Ajax/CSS表格设计
  2. JavaScript作为内联块去间距的强大黑客
  3. Converting multiple files into HTML (f
  4. HTML网页开发基础1
  5. 如何在动态生成的表行jquery中添加和操作
  6. 我想在html文件里插入一个for循环,应该如
  7. 如何在localStorage中存储数组?(复制)
  8. 我无法在某些Web浏览器中输入我的注册文
  9. html 引用文件编码为utf-8 的 js文件乱码
  10. 对于MVC中的循环不适用于不同的MapRoute