目前從事無人機配套程式開發,之前一直使用的是RTMP進行直播流顯示,由于網頁端要棄用flash,轉為使用WebRtc協定,改完後RTMP流延遲飙升,遂安卓端同步修改。
由于網絡上大部分教程文章都是多人視訊示例且不了解SRS和WebRtc通信流程 浪費了很多時間
本文章隻涉及安卓端的webrtc流播放 适用于SRS推流
參考以下文章 macaruina
WebRTC源碼研究(29)媒體能力協商過程
Web項目jswebrtc
SRS測試位址
1.SRS WebRtc通信流程
安卓端作為調用方 正常流程為由stable開始
createOffer->setLocalDescription->接收answer->setRemoteDescription
這裡由于SRS的存在 接收answer這一步驟需要手動使用網絡請求伺服器進行建立answer操作 如下
請求接口後SRS會建立answer 并在接口傳回Json資料包含spd 安卓端直接調用setRemoteDescription即可
2.安卓端整體代碼
build.gradle
implementation 'org.webrtc:google-webrtc:1.0.32006'
布局
<org.webrtc.SurfaceViewRenderer
android:id="@+id/activity_main_svr_video"
android:layout_width="match_parent"
android:layout_height="match_parent" />
初始化EglBase PeerConnectionFactory
//初始化EglBase macaruina
EglBase.Context eglBaseContext = EglBase.create().getEglBaseContext();
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions
.builder(context)
.createInitializationOptions());
//初始化PeerConnectionFactory macaruina
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
DefaultVideoEncoderFactory encoderFactory =
new DefaultVideoEncoderFactory(eglBaseContext, true, true);
DefaultVideoDecoderFactory decoderFactory =
new DefaultVideoDecoderFactory(eglBaseContext);
PeerConnectionFactory peerConnectionFactory = PeerConnectionFactory.builder()
.setOptions(options)
.setVideoEncoderFactory(encoderFactory)
.setVideoDecoderFactory(decoderFactory)
.createPeerConnectionFactory();
//初始化SurfaceViewRenderer
surfaceViewRenderer.init(eglBaseContext, null);
//初始化peerConnectionFactory監聽 macaruina
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(new ArrayList<>());
//修改模式 PlanB無法使用僅接收音視訊的配置
rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig,
new PeerConnection.Observer() {
......
@Override
public void onAddStream(MediaStream mediaStream) {
//在這裡将流放進surfaceViewRenderer中 macaruina
mediaStream.videoTracks.get(0).addSink(surfaceViewRenderer);
}
......
});
//設定僅接收音視訊
peerConnection.addTransceiver(MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO, new RtpTransceiver.RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.RECV_ONLY));
peerConnection.addTransceiver(MediaStreamTrack.MediaType.MEDIA_TYPE_AUDIO, new RtpTransceiver.RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.RECV_ONLY));
peerConnection.createOffer(sdpObserver, new MediaConstraints());
SdpObserver sdpObserver = new SdpObserver() {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
if (sessionDescription.type == SessionDescription.Type.OFFER) {
//設定setLocalDescription offer傳回sdp macaruina
peerConnection.setLocalDescription(sdpObserver, sessionDescription);
//請求SRS伺服器接口 macaruina
//HttpPost.....網絡請求 得到結果後調用setRemoteDescription 傳入傳回的sdp
}
}
......
};
void setRemoteDescription(String sdp) {
SessionDescription remoteSpd = new SessionDescription(SessionDescription.Type.ANSWER, sdp);
peerConnection.setRemoteDescription(sdpObserver, remoteSpd);
}