Android設備一對多錄屏直播--(UDP組播鏈接,Tcp傳輸)

原文:http://www.javashuo.com/article/p-kllvawqr-gb.html網絡

 

近期須要學習流媒體知識,作一個Android設備相互投屏Demo,所以找到了這個博主寫的,看了好久也同該博主交流探索了許久,很是感謝該博主。數據結構

這位博主介紹了Android之間互相的錄屏直播 --點對點傳輸(tcp長鏈接發送h264),詳細介紹了h264的數據結構,對於剛學習流媒體的人來講是很好的福利,很少說附上地址:socket

來自:baidu_33546245的博客
(1) Android之間互相的錄屏直播 –點對點傳輸(tcp長鏈接發送h264)(一)
https://blog.csdn.net/baidu_33546245/article/details/78670220
(2)Android之間互相的錄屏相機直播-(增長聲音直播)(二)
https://blog.csdn.net/baidu_33546245/article/details/80503091tcp

Demo下載地址:
採集端——ScreenImage
播放端——ScreenImagePlayide

本項目實現講解,具體會分爲三篇,分別是鏈接,傳輸,優化 :工具

篇二: Android設備一對多錄屏直播——(音視頻採集,Tcp傳輸)oop

在研究瞭解以後,我在此demo基礎上加了使用Udp組播鏈接,Tcp進行通信傳輸,一對多投屏,點擊中止投屏,服務端自動切換下一個設備 :post

 

由於上傳圖片大小有限,因此只能壓縮壓縮再壓縮了,畫質也只能這樣了。在這個過程當中發現了一個比較好的工具,將video轉換成gif,而後還能壓縮,附上地址:學習

視頻處理工具:https://ezgif.com/optimize/ezgif-4-40cf5d3c0c.gif優化

由於動圖畫質比較模糊,我再此說一下總體demo的實現

手機A(MI 4LT)和手機B(MX4)進入程序自動鏈接上了播放端。
採集端:手機A和手機B主界面上是倆個按鈕,分別是「開始投屏」和「中止投屏」 ,相繼點擊A,B倆臺手機的開始投屏。
播放端:接收到手機A的消息,播放A手機視頻。
當手機A(MI 4LT)點擊中止投屏,播放端自動切換到手機B(MX4),播放視頻,看動圖切換信息ui的更改是能看清的。
這裏我是根據業務需求自動切換下一個設備,而不是讓下一個設備搶佔,這個後續你們根據本身須要,自行選擇。
上時序圖
​​​​​​

講代碼

設備鏈接——UDP組播
以前採用tcp進行鏈接的時候,發現當多臺設備要進行投屏的時候並不太好的適用,而後技術Leader就提醒了我用組播。
關於組播:
組播是一對多的傳輸方式,其中有個組播組的概念,發送端將數據向一個組內發送,網絡中的路由器經過底層的IGMP協議自動將數據發送到全部監聽這個組的終端。至於廣播則和組播有一些類似,區別是路由器向子網內的每個終端都投遞一份數據包,不論這些終端是否樂於接收該數據包。UDP廣播只能在內網(同一網段)有效,而組播能夠較好實現跨網段羣發數據。

1.服務端(播放端):建立UDP組播服務

獲取當前的網絡IP地址,這裏枚舉了本機全部的網絡地址,只返回ipv4
// TODO: 2018/7/12 獲取本地全部ip地址
public static String getLocalIpAddress() {
String address = null;
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();
enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
address = inetAddress.getHostAddress().toString();
//ipV6
if (!address.contains("::")) {
return address;
}
}
}
}
} catch (SocketException ex) {
Log.e("getIpAddress Exception", ex.toString());
}
return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
初始化組播
private void initData() {
ip = null;
try {
while (ip == null) {
ip = getAddressIP();
}
inetAddress = InetAddress.getByName(BROADCAST_IP);//多點廣播地址組
multicastSocket = new MulticastSocket(BROADCAST_PORT);//多點廣播套接字
multicastSocket.setTimeToLive(1);
multicastSocket.joinGroup(inetAddress);
Log.e("UdpService", "start multcast socket");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (ip != null) {
//開始廣播
new UDPBoardcastThread(context, ip, inetAddress, multicastSocket,
BROADCAST_PORT, weakHandler, this);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
這裏要注意組播的地址範圍,到時候客戶端也要保持相應的
注:組播使用UDP對必定範圍內的地址發送相同的一組Packet,即一次能夠向多個接受者發出信息,其與單播的主要區別是地址的形式。IP協議分配了必定範圍的地址空間給多播(多播只能使用這個範圍內的IP),IPv4中組播地址範圍爲224.0.0.0到239.255.255.255,其中224.0.0.0爲系統自用。

 

開線程,發送數據(把播放端這邊的IP地址發過去,採集端那邊鏈接後拿到IP地址進行TCP鏈接)
@Override
public void run() {
DatagramPacket dataPacket = null;
//將本機的IP地址放到數據包裏
byte[] data = ip.getBytes();
dataPacket = new DatagramPacket(data, data.length, inetAddress, broadcastPort);
//判斷是否中斷鏈接了
while (AboutNetUtils.isNetWorkConnected(context)) {
try {
//Log.e("123:","再次發送ip地址廣播");
multicastSocket.send(dataPacket);
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
}
weakHandler.post(new Runnable() {
@Override
public void run() {
listener.udpDisConnec();
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2.客戶端(採集端):接收廣播,創建鏈接

開線程,監聽端口,加入廣播
實例化MulticastSocket對象,並指定端口
加入廣播地址,MulticastSocket使用public void joinGroup(InetAddress mcastaddr)
開始接收廣播
關閉廣播
@Override
public void run() {
MulticastSocket multicastSocket = null;//多點廣播套接字
try {
/**
* 1.實例化MulticastSocket對象,並指定端口
* 2.加入廣播地址,MulticastSocket使用public void joinGroup(InetAddress mcastaddr)
* 3.開始接收廣播
* 4.關閉廣播
*/
multicastSocket = new MulticastSocket(BROADCAST_PORT);
inetAddress = InetAddress.getByName(BROADCAST_IP);
Log.e("UdpClientThread", "udp server start");
multicastSocket.joinGroup(inetAddress);
byte buf[] = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
while (true) {
multicastSocket.receive(dp);
Log.e("UdpClientThread", "receive a msg");
ip = new String(buf, 0, dp.getLength());
multicastSocket.leaveGroup(inetAddress);
multicastSocket.close();
MyApplication.mHandler.post(new Runnable() {
@Override
public void run() {
mListener.udpConnectSuccess(ip);
}
});
}
} catch (Exception e) {
MyApplication.mHandler.post(new Runnable() {
@Override
public void run() {
mListener.udpDisConnec(e.getMessage());
}
});
} finally {
Log.e("UdpClientThread", "udp server close");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
數據傳輸——TCP傳輸
上面仔細看代碼的應該知道從udp鏈接的時候,客戶端這邊已經拿到了IP,這邊拿到IP後,在點擊開始錄屏按鈕時,去調用屏幕錄製,點擊系統彈出框開始錄製時,去創建TCP鏈接。

這邊具體的TCP鏈接就不貼圖了,到時候具體看代碼,這邊我主要說下一對多的投屏步驟。由於要說的東西不少,這邊我分爲三章。Android設備一對多錄屏直播——(音視頻採集,Tcp傳輸)

相關文章
相關標籤/搜索