原文:https://blog.csdn.net/sunmmer123/article/details/82734245

近期需要学习流媒体知识,做一个Android设备相互投屏Demo,因此找到了这个博主写的,看了很久也同该博主交流探索了许久,非常感谢该博主。

这位博主介绍了Android之间互相的录屏直播 --点对点传输(tcp长连接发送h264),详细介绍了h264的数据结构,对于刚学习流媒体的人来说是很好的福利,不多说附上地址:

来自: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/80503091

Demo下载地址:
采集端——ScreenImage
播放端——ScreenImagePlay

本项目实现讲解,具体会分为三篇,分别是连接,传输,优化 :

篇二: Android设备一对多录屏直播——(音视频采集,Tcp传输)

在研究了解之后,我在此demo基础上加了使用Udp组播连接,Tcp进行通讯传输,一对多投屏,点击停止投屏,服务端自动切换下一个设备 :

因为上传图片大小有限,所以只能压缩压缩再压缩了,画质也只能这样了。在这个过程中发现了一个比较好的工具,将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传输)

Demo下载地址:
采集端——ScreenImage
播放端——ScreenImagePlay
---------------------
作者:W_D_T
来源:CSDN
原文:https://blog.csdn.net/sunmmer123/article/details/82734245
版权声明:本文为博主原创文章,转载请附上博文链接!

Android设备一对多录屏直播--(UDP组播连接,Tcp传输)的更多相关文章

  1. Android实现录屏直播(三)MediaProjection + VirtualDisplay + librtmp + MediaCodec实现视频编码并推流到rtmp服务器

    请尊重分享成果,转载请注明出处,本文来自Coder包子哥,原文链接:http://blog.csdn.net/zxccxzzxz/article/details/55230272 Android实现录 ...

  2. Android实现录屏直播(一)ScreenRecorder的简单分析

    http://blog.csdn.net/zxccxzzxz/article/details/54150396 Android实现录屏直播(一)ScreenRecorder的简单分析 Android实 ...

  3. Android实现录屏直播(二)需求才是硬道理之产品功能调研

    请尊重分享成果,转载请注明出处,本文来自Coder包子哥,原文链接:http://blog.csdn.net/zxccxzzxz/article/details/54254244 前面的Android ...

  4. 手游录屏直播技术详解 | 直播 SDK 性能优化实践

    在上期<直播推流端弱网优化策略 >中,我们介绍了直播推流端是如何优化的.本期,将介绍手游直播中录屏的实现方式. 直播经过一年左右的快速发展,衍生出越来越丰富的业务形式,也覆盖越来越广的应用 ...

  5. ARDC Android 远程桌面助手 录屏 演示 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  6. Windows 11实现录屏直播,搭建Nginx的rtmp服务

    先!下载几个工具呗 官方下载FFmpeg:http://www.ffmpeg.org 官方下载nginx-rtmp-module:https://github.com/arut/nginx-rtmp- ...

  7. Windows11实现录屏直播,H5页面直播 HLS ,不依赖Flash

    这两天的一个小需求,需要实现桌面实时直播,前面讲了两种方式: 1.Windows 11实现录屏直播,搭建Nginx的rtmp服务 的方式需要依赖与Flash插件,使用场景有限 2.Windows 11 ...

  8. Android上UDP组播无法接收数据的问题

    最近,想做一个跨平台的局域网的文件传输软件,思路是组播设备信息,TCP连接传输文件.于是进行了一次简单的UDP组播测试,发现Android对于UDP组播接收数据的支持即极为有限. 部分代码如下 pac ...

  9. C# 使用UDP组播实现局域网桌面共享

    最近需要在产品中加入桌面共享的功能,暂时不用实现远程控制:参考了园子里的一些文章,加入了一些自己的修改. 需求:将一台机器的桌面通过网络显示到多个客户端的屏幕上,显示内容可能为PPT,Word文档之类 ...

随机推荐

  1. python实战===教你用微信每天给女朋友说晚安【转】

    转自:https://www.cnblogs.com/botoo/p/8622379.html#4081184 但凡一件事,稍微有些重复.我就考虑怎么样用程序来实现它. 这里给各位程序员朋友分享如何每 ...

  2. 10 个 MySQL 经典错误【转】

    Top 1:Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行) 问题还原 mysql> show variables like '%max_connec ...

  3. C++ 读取字符串中的数字

    今天真是试了各种方法,笨方法聪明方法都有了 方法1:一个字符一个字符的读取 方法2:借助strtok实现split 适用于char 方法3:借助istringstream实现split 适用于stri ...

  4. LNMP下Nginx 中文文件名或目录404无法访问的解决方法

    貌似很多人还是会遇到中文乱码的问题,Apache可以使用mod_encoding支持中文目录和文件,LNMP下Nginx其实不需要安装额外的组件即可支持中文文件名或中文目录,下面说一下常见的CentO ...

  5. $Django setting.py配置 ,GET、POST深入理解,三件套,orm对象关系映射简介

    1 django中app的概念: 大学:----------------- 项目  信息学院 ----------app01  物理学院-----------app02 ****强调***:创建的每一 ...

  6. PDF阅读器中如何改变线条颜色、线宽和线型等

    1.打开PDF阅读器过后,点击菜单栏"注释"这一栏,找到绘图区域中的线条或铅笔: 2.分别用线条和铅笔随意画两条直线,然后选中直线,右键点击直线并打开"属性": ...

  7. [Linux]PHP-FPM与NGINX的两种通讯方式

    一.通过监听TCP端口通讯 php-fpm.d/www.conf ; The address on which to accept FastCGI requests. ; Valid syntaxes ...

  8. SP2-0734: 未知的命令开头 "exp wlc/ra..." - 忽略了剩余的行。

    SP2-0734: 未知的命令开头 "exp wlc/ra..." - 忽略了剩余的行. 原来只需要在  $exp wlc/radial_wlc123@ora11g owner=w ...

  9. swift 实践- 14 -- UIScrollView

    import UIKit class ViewController: UIViewController ,UIScrollViewDelegate{ override func viewDidLoad ...

  10. 2。创建第一个angular应用,已经开发前的一些配置

    现在我们开始新建一个angular5的脚手架  . 到想要建项目的目录下.比如我的 在  D:\JsProjects 进入cmd或者powershell cd 进入该文件夹下 然后开始新建,ng ne ...