一、实现目标

  iOS11.0以上设备通过USB线连接电脑,在电脑端实时看到手机屏幕内容

  画质达到超清720级别,码率可达到1Mbps以上

二、实现技术方案设计

  1、手机端采用ReplayKit2框架,在Upload Extension 进程中采集到屏幕内容YUV和系统声音PCM+麦克风声音PCM

  

- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
switch (sampleBufferType) {
case RPSampleBufferTypeVideo:
break;
case RPSampleBufferTypeAudioApp:
break;
case RPSampleBufferTypeAudioMic:
break;
default:
break;
}
}

  2、考虑在在Upload Extension 进程中或者主App进程中对图像和声音进行编码,编码成H264+AAC ,然后封装为FLV格式的包,利用RTMP协议进行推流

    因为目前已经存在一套推流的接口,所以考虑在PC端增加RTMP收流服务,进行解析视频流,然后渲染

  3、在PC端建立RTMP收流服务端,解码,渲染;目前OBS已经存在相关模块

三、遇到的问题以及解决方案

  1、如果在局域网中,目前的基础上,无线推流到PC和推流到远程直播服务器流程基本一样

  2、如何规避局域网的网络抖动环境,实现高清推流?局域网可能因为多人使用导致带宽分配原因,以及信道干扰原因导致上行速率达不到标称要求

    采用有线方案可以解决这个问题,那么手机如何利用USB线传递数据?

  3、USB传递有线数据有两种方案:

    第一种是MIFI认证,使用iOS外设通信的库,ExternalAccessory

    第二种是通过iproxy , 在PC端执行"iproxy pcport mobileport"的方式实现端口转发,PC上连接pcport会连接到手机的mobileport,当一条TCP连接建立成功之后手机就可以利用USB线和PC实现双向通信了

    这里为什么不能像安卓一样,实现正向的转发,将手机的端口转发到PC上呢?这就是iOS系统相对封闭的原因;

    猜测安卓连接USB线的时候,PC端执行命令会在手机端出发操作实现端口转发规则;而iOS不行

  那么最终采用的是第二种方案。

四、推流SDK协议改造

  对于采用的第二种方案,实施的时候遇到两个问题?

  第一个如何实现由PC主动连接手机的过程,连接手机的哪个端口?

    对于这个问题,这里解决方案是,第一个在socket上面设置套接字为REUSE相关的属性,保证端口能够重复绑定成功,这里假定这个1397端口只有这个程序使用

                   第二个是在有线投屏的时候,手机要先扫码得到PC的一个key,手机在启动一个TCP监听后将端口号联系这个key一起发给我们的后台,后台通过push或者pc pull的方式,将这个信息通知到PC端,也就是建立信道的方式

  第二个问题,如何在一个RTMP.c的主动发起连接中,修改原有的方式,先尝试被动连接(先启动一个同步阻塞的监听socket等待PC连接)。在这个逻辑中,因为等待过程是阻塞的,必然涉及到延时,在这里遇到了坑

    我们希望在 tcp socket bind一个端口,然后listen,然后accept的时候,希望在accept这个方法实现超时逻辑,最开始是这样实现的

    

 int ret = ::setsockopt(m_nRealServerSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &tv, sizeof(tv));
LOGW("socket accept start 1, set timeout ret = %d", ret);
ret = ::setsockopt(m_nRealServerSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*) &tv, sizeof(tv));

    上述的代码在安卓和PC上面生效,但是在iOS平台上面无效,虽然设置了一个超时时间,但是这个超时永远不会触发,accept永久阻塞

    为了规避这个问题,我采用select监听文件描述符的方式,select跨平台兼容性效果更好

    采用以下代码实现accept超时逻辑:

        int fd = -1;
fd_set fdflag;
sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(client_addr)); FD_ZERO(&fdflag);
FD_SET(m_nRealServerSocket, &fdflag); LOGW("socket accept start, timeout = %d secs", tv.tv_sec);
bool hasProcessConnect = false;
if(!hasProcessConnect && select(m_nRealServerSocket + 1, &fdflag, NULL, NULL, &tv) > 0)
{
hasProcessConnect = true;
fd = accept(m_nRealServerSocket, (struct sockaddr*)NULL, NULL);
}
// 一次事件触发之后, 清理监控的描述符
FD_ZERO(&fdflag);

  

五、最终效果

ReplayKit2 有线投屏项目总结的更多相关文章

  1. mac电脑怎么投屏?教你选择适合自己的Mac投屏软件

    mac上有什么好的投屏软件嘛?苹果手机ios投屏到mac用哪款投屏软件,mac投屏ipad该用哪款软件怎么操作,macdown小编给大家介绍的这几款Mac投屏软件,各有各的特色,总有一款适合你投屏. ...

  2. 看完小白也会使用,Android投屏神器scrcpy详细教程

    楔子 做为一个软件测试工程师,在使用手机测试的时候,缺陷附件想附上截图.视频,需要从手机把图片.视频发送到拷贝或发送到电脑,非常麻烦. 所以想到使用投屏软件,把手机的屏幕投屏到电脑,便可以直接在电脑上 ...

  3. ios11苹果手机怎么投屏到电脑

    使用过苹果手机的用户都知道,苹果手机触摸屏操作极为流畅,网页浏览也非常轻松,各种网络上的应用可以说是非常完美.iPhone的娱乐功能相当的强大,能让苹果iPhone超越了其他手机很大的距离.但是手机怎 ...

  4. 安卓投屏助手(B1358)之辅助调试

    Android远程桌面助手的中文版——安卓投屏助手正式上线.安卓投屏和远程控制的软件其实已经非常多了,如Vysor.Total Control.Mobizen.ApowerMirror.TeamVie ...

  5. ios屏幕怎么投屏到电脑显示器

    iphone在国内一直都很受欢迎,为什么这么受欢迎呢?其实苹果手机操作系统非常的新颖,让人对手机有了重新的认识.但是ios屏幕怎么投屏到电脑显示器.感兴趣的一起阅读下面的内容吧! 使用工具: 苹果手机 ...

  6. 安卓手机如何快速投屏到windows(10/8.1/7)电脑上

    前提: 手机和电脑连接的网络必须在同一局域网下. 优势: 手机和电脑不需要下载对应平台的应用,完全使用全系统自带功能. 附加: 以下演示是安卓手机和windows操作系统电脑,并且win10和win1 ...

  7. iPhone手机怎么投屏到电脑上

    如今生活水平不断上升,人们更加追求高质量.高享受的生活,所以可以利用一切资源提高生活质量,享受更好的生活体验,比如说手机投屏电脑就可以提高我们的视觉体验,所以更多的人去尝试,那么iPhone手机怎么投 ...

  8. iPhone手机怎么投屏到电脑 airplay在哪里设置

    iPhone手机怎么投屏到电脑?想要小屏转大屏,其实方法很简单,简单几步就可以操作,下面简单几步教大家手机投屏电脑的方法. 使用工具: Iphone&电脑 操作方法: 1.如果想要把手机本地的 ...

  9. iphone屏幕镜像怎么用 手机投屏电脑

    手机看视频有的时候总会感觉到累,屏幕太小看的不够爽又或者用手一直拿着手机看累得慌.我就就喜欢看电视因为电视屏幕大看的爽,而且现在很多手机视频都可以往电视上投影视频,那么iphone屏幕镜像怎么用? 使 ...

  10. 苹果手机如何投屏到win10电脑上

    苹果手机中的IOS系统比安卓系统的确好用.苹果手机使用多久都不会出现手机卡顿的现象,一如既往的流畅自如,这就是人们追求苹果机的原因之一.苹果手机朋友们可能会觉得手机屏幕太小影响视觉怎么办,苹果手机如何 ...

随机推荐

  1. springboot获取七牛云空间文件列表及下载功能

    原文摘自:https://www.codernav.com 第一步:新建springboot项目,引入jar包,其中hutool-all是工具类,用来写文件下载,可以随意更换. <!--工具类- ...

  2. easyx的使用 鼠标交互(3.1)

    本文学习于B站,进行借鉴学习记录: 视频链接:鼠标操作(新版)_哔哩哔哩_bilibili 初始化调用文件头不再使用#include<graphics.h>,选择调用#include< ...

  3. Fluid 助力阿里云 Serverless 容器极致提速

    简介: 本文展示了一个在 ASK 环境中运行 Fluid 的完整数据访问示例,希望能够帮助大家了解 Fluid 的使用体验.运行效果以及 Serverless 和数据密集型应用结合的更多可行性. 作者 ...

  4. 阿里云数据库开源重磅发布:PolarDB三节点高可用的功能特性和关键技术

    ​简介:在3月2日的阿里云开源 PolarDB 企业级架构发布会上,阿里云数据库技术专家孟勃荣 带来了主题为<PolarDB 三节点高可用>的精彩演讲.三节点高可用功能主要为 PolarD ...

  5. 自建Kubernetes集群如何使用弹性容器实例ECI

    简介: 虚拟节点(Virtual Node)实现了Kubernetes与弹性容器实例ECI的无缝连接,让Kubernetes集群轻松获得极大的弹性能力,而不必受限于集群的节点计算容量.您可以灵活动态的 ...

  6. Jaeger插件开发及背后的思考

    ​简介: 本文主要介绍Jaeger最新的插件化后端的接口以及开发方法,让大家能够一步步的根据文章完成一个Jaeger插件的开发.此外SLS也推出了对于Jaeger的支持,欢迎大家试用. 随着云原生 + ...

  7. [FAQ] Windows 终端 git status 不识别文件名大小写的修改

      当我们修改了文件名的大小写,git status 显示没有文件改动. 出现这种情况,首先看一下 git 的配置项是否忽略了文件问大小写: $ git config core.ignorecase ...

  8. dotnet 警惕 Task 的 ContinueWith 带上 OnlyOnFaulted 参数抛出取消异常

    本文记录 dotnet 的一个令人迷惑的设计,在 Task 里,有一个叫 ContinueWith 的方法,此方法可以在 Task 完成时执行传入的委托.在 ContinueWith 方法里面,还有一 ...

  9. games101-3 BRDF101

    BRDF101 概述 本文基于知乎Maple对brdf的文章,在此基础又收集了一些其它来源的关于brdf的文章,希望能够完全理解记忆相关知识 关于Jakub Boksansky的文章,看的过程中又去搜 ...

  10. shell 调试方法

    shell 在 linux 系统中比较常见,简单的脚本可以看着确实没难度,但是当脚本功能复杂后,看起来就不那么流畅了,所以掌握一些调试方式还是很有必要的,这里我收集了一次常用的调试方式. shell调 ...