转载请注明出处:https://blog.csdn.net/sunmmer123

近期需要学习流媒体知识,做一个Android设备相互投屏Demo,因此找到了这个博主写的,看了很久也同该博主交流探索了许久,非常感谢该博主。
这位博主介绍了Android之间互相的录屏直播 --点对点传输(tcp长连接发送h264),详细介绍了h264的数据结构,对于刚学习流媒体的人来说是很好的福利,不多说附上地址:

baidu_33546245的博客 (https://blog.csdn.net/baidu_33546245?t=1)

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

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

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


在研究了解之后,我在此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的更改是能看清的。
  • 这里我是根据业务需求自动切换下一个设备,而不是让下一个设备抢占,这个后续大家根据自己需要,自行选择。

上时序图
​​​​​​Android设备一对多录屏直播--(UDP组播连接,Tcp传输)_第1张图片


讲代码

设备连接——UDP组播

  • 之前采用tcp进行连接的时候,发现当多台设备要进行投屏的时候并不太好的适用,然后技术Leader就提醒了我用组播。

关于组播:
组播是一对多的传输方式,其中有个组播组的概念,发送端将数据向一个组内发送,网络中的路由器通过底层的IGMP协议自动将数据发送到所有监听这个组的终端。至于广播则和组播有一些相似,区别是路由器向子网内的每一个终端都投递一份数据包,不论这些终端是否乐于接收该数据包。UDP广播只能在内网(同一网段)有效,而组播可以较好实现跨网段群发数据。

1.服务端(播放端):创建UDP组播服务

  • 获取当前的网络IP地址,这里枚举了本机所有的网络地址,只返回ipv4
    // TODO: 2018/7/12 获取本地所有ip地址    public static String getLocalIpAddress() {        String address = null;        try {            for (Enumeration en = NetworkInterface.getNetworkInterfaces();                 en.hasMoreElements(); ) {                NetworkInterface intf = en.nextElement();            for (Enumeration 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;    }
  • 初始化组播
    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);        }    }
  • 这里要注意组播的地址范围,到时候客户端也要保持相应的

注:组播使用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();            }        });    }

2.客户端(采集端):接收广播,建立连接

  • 开线程,监听端口,加入广播
    1. 实例化MulticastSocket对象,并指定端口
    2. 加入广播地址,MulticastSocket使用public void joinGroup(InetAddress mcastaddr)
    3. 开始接收广播
    4. 关闭广播
  @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");        }    }

数据传输——TCP传输

上面仔细看代码的应该知道从udp连接的时候,客户端这边已经拿到了IP,这边拿到IP后,在点击开始录屏按钮时,去调用屏幕录制,点击系统弹出框开始录制时,去建立TCP连接。

这边具体的TCP连接就不贴图了,到时候具体看代码,这边我主要说下一对多的投屏步骤。
因为要说的东西很多,这边我分为三章。
Android设备一对多录屏直播——(音视频采集,Tcp传输)

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

更多相关文章

  1. 电脑控制Android设备的软件——Total Control
  2. NVIDIA Tegra3,高通S4 MSM8960,三星Exynos4【新一代手机处理器大比
  3. Android中抓取手机视频流数据。
  4. Android 定位地址,获取经纬度,并转换为中文地址
  5. Android系统信息获取 之七:获取IP地址和MAC地址
  6. 分享我开发的网络电话Android手机APP正式版,图文详解及下载
  7. iPhone和Android智能手机浏览器判断分辨率问题
  8. 【Android】手机端的投射

随机推荐

  1. android之自定义Dialog
  2. android点击按钮控制图片切换-kotlin
  3. 如何在XML设定android控件的颜色(十六进制
  4. android 线程池的使用
  5. Android(安卓)源码获取-----在Windows环
  6. android中一些配置文件的参数的意义
  7. Android小程序-Walker注册页面(四)
  8. Android 如何使Edittext不弹出软键盘
  9. android UI进阶之弹窗的使用(2)--实现通讯
  10. Android(安卓)Debug Bridge(ADB) 技术实