ReplayKit2 有线投屏项目总结
一、实现目标
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 有线投屏项目总结的更多相关文章
- mac电脑怎么投屏?教你选择适合自己的Mac投屏软件
mac上有什么好的投屏软件嘛?苹果手机ios投屏到mac用哪款投屏软件,mac投屏ipad该用哪款软件怎么操作,macdown小编给大家介绍的这几款Mac投屏软件,各有各的特色,总有一款适合你投屏. ...
- 看完小白也会使用,Android投屏神器scrcpy详细教程
楔子 做为一个软件测试工程师,在使用手机测试的时候,缺陷附件想附上截图.视频,需要从手机把图片.视频发送到拷贝或发送到电脑,非常麻烦. 所以想到使用投屏软件,把手机的屏幕投屏到电脑,便可以直接在电脑上 ...
- ios11苹果手机怎么投屏到电脑
使用过苹果手机的用户都知道,苹果手机触摸屏操作极为流畅,网页浏览也非常轻松,各种网络上的应用可以说是非常完美.iPhone的娱乐功能相当的强大,能让苹果iPhone超越了其他手机很大的距离.但是手机怎 ...
- 安卓投屏助手(B1358)之辅助调试
Android远程桌面助手的中文版——安卓投屏助手正式上线.安卓投屏和远程控制的软件其实已经非常多了,如Vysor.Total Control.Mobizen.ApowerMirror.TeamVie ...
- ios屏幕怎么投屏到电脑显示器
iphone在国内一直都很受欢迎,为什么这么受欢迎呢?其实苹果手机操作系统非常的新颖,让人对手机有了重新的认识.但是ios屏幕怎么投屏到电脑显示器.感兴趣的一起阅读下面的内容吧! 使用工具: 苹果手机 ...
- 安卓手机如何快速投屏到windows(10/8.1/7)电脑上
前提: 手机和电脑连接的网络必须在同一局域网下. 优势: 手机和电脑不需要下载对应平台的应用,完全使用全系统自带功能. 附加: 以下演示是安卓手机和windows操作系统电脑,并且win10和win1 ...
- iPhone手机怎么投屏到电脑上
如今生活水平不断上升,人们更加追求高质量.高享受的生活,所以可以利用一切资源提高生活质量,享受更好的生活体验,比如说手机投屏电脑就可以提高我们的视觉体验,所以更多的人去尝试,那么iPhone手机怎么投 ...
- iPhone手机怎么投屏到电脑 airplay在哪里设置
iPhone手机怎么投屏到电脑?想要小屏转大屏,其实方法很简单,简单几步就可以操作,下面简单几步教大家手机投屏电脑的方法. 使用工具: Iphone&电脑 操作方法: 1.如果想要把手机本地的 ...
- iphone屏幕镜像怎么用 手机投屏电脑
手机看视频有的时候总会感觉到累,屏幕太小看的不够爽又或者用手一直拿着手机看累得慌.我就就喜欢看电视因为电视屏幕大看的爽,而且现在很多手机视频都可以往电视上投影视频,那么iphone屏幕镜像怎么用? 使 ...
- 苹果手机如何投屏到win10电脑上
苹果手机中的IOS系统比安卓系统的确好用.苹果手机使用多久都不会出现手机卡顿的现象,一如既往的流畅自如,这就是人们追求苹果机的原因之一.苹果手机朋友们可能会觉得手机屏幕太小影响视觉怎么办,苹果手机如何 ...
随机推荐
- 重新点亮shell————awk数组[十四]
前言 简单介绍一下awk的数组. 正文 数组的定义: 数组的遍历: 删除数组: 例子: 例子2: 结 下一节awk函数.
- c# 深克隆与浅克隆
前言 我们都知道memberwiseclone 会将浅克隆. 什么是浅克隆?如何深克隆呢? 正文 public class good{ private good(){ oneclass=new cla ...
- JS isPrototypeOf 和hasOwnProperty 还有in的区别
isPrototypeOf 和hasOwnProperty 的区别 isPrototypeOf 是判断原生链上是否有该对象. 1.isPrototypeOf isPrototypeOf是用来判断指定对 ...
- 安装以及破解Navicat
1.下载Navicat软件安装包 链接:https://pan.baidu.com/s/1RltCPjg1mmpOjC7vxAjQ4g 提取码:v4k8 2.下载好文件打开是这样的,先运行 " ...
- 牛客网-SQL专项练习4
①向表evaluate的成绩列添加成绩,从表grade中的成绩一列提取记录,SQL语句为: INSERT INTO evaluate(grade.point) SELECT grade.point ...
- 力扣171(java)-Excel表列序号(简单)
题目: 给你一个字符串 columnTitle ,表示 Excel 表格中的列名称.返回 该列名称对应的列序号 . 例如: A -> 1B -> 2C -> 3...Z -> ...
- 基于MaxCompute的大数据安全方案
简介:随着法律的完善,数据安全,信息安全,网络安全,升级成国家安全,所以数据安全不管对用户,还是对公司也都会变的越来越重要.做为大数据云数仓解决方案的领导者,阿里云MaxCompute在安全体系上也 ...
- 人人都是 Serverless 架构师 | 现代化 Web 应用开发实战
简介:本篇实战将介绍如何以超低成本构建动态的 Web 站点,并且实现灵活扩展,限流等效果,最后再跟大家聊一聊"现代应用"的相关概念. 相信很多同学都有过想要拥有自己的 Web 站 ...
- MongoDB 5.0新特性概览
简介: MongoDB 5.0标志着一个新的发布周期的到来,以更快地交付新特性给到用户.版本化API与在线重新分片相结合,使用户不必担心未来的数据库升级以及业务变化问题:本地原生时间序列数据平台也使 ...
- dotnet C# 基于 INotifyPropertyChanged 实现一个 CLR 属性绑定辅助类
习惯了 WPF 或 UWP 等的依赖属性的绑定机制之后,我在写 CLR 属性时,有时也期望将两个 CLR 属性给绑定到一起.在 dotnet 里,提供了 System.ComponentModel.I ...