Android投屏(屏幕共享)设计需要考虑的关键因素

许多开发者,在做智慧教室同屏、会议同屏之类的方案时,基于Andriod平台的采集,往往遇到各种各样的问题,以下就几个点,抛砖引玉:

1. 内网环境下,组播还是RTMP?

回答:这个问题,被无数的开发者问到,为此,单独写了篇博客论证:https://blog.csdn.net/renhui1112/article/details/86741428,感兴趣的可以参考下,简单来说,能RTMP的,就RTMP,如果真是内网环境下,没有并发瓶颈的同屏,可以启动内置RTSP服务(走单播),然后,其他终端拉流也不失为一个好的方案。

2. 推送分辨率如何设定或缩放?

回答:一般来说,好多Android设备,特别是高分屏,拿到的视频原始宽高非常大,如果推原始分辨率,编码和上行压力大,所以,一般建议,适当缩放,比如宽高缩放至2/3,缩放一般建议等比例缩放,此外,缩放宽高建议16字节对齐。

废话不多说,上实例代码:

    private void createScreenEnvironment() {sreenWindowWidth = mWindowManager.getDefaultDisplay().getWidth();screenWindowHeight = mWindowManager.getDefaultDisplay().getHeight();Log.i(TAG, "screenWindowWidth: " + sreenWindowWidth + ",screenWindowHeight: "+ screenWindowHeight);if (sreenWindowWidth > 800){if (screenResolution == SCREEN_RESOLUTION_STANDARD){scale_rate = SCALE_RATE_HALF;sreenWindowWidth = align(sreenWindowWidth / 2, 16);screenWindowHeight = align(screenWindowHeight / 2, 16);}else if(screenResolution == SCREEN_RESOLUTION_LOW){scale_rate = SCALE_RATE_TWO_FIFTHS;sreenWindowWidth = align(sreenWindowWidth * 2 / 5, 16);}}Log.i(TAG, "After adjust mWindowWidth: " + sreenWindowWidth + ", mWindowHeight: " + screenWindowHeight);int pf = mWindowManager.getDefaultDisplay().getPixelFormat();Log.i(TAG, "display format:" + pf);DisplayMetrics displayMetrics = new DisplayMetrics();mWindowManager.getDefaultDisplay().getMetrics(displayMetrics);mScreenDensity = displayMetrics.densityDpi;mImageReader = ImageReader.newInstance(sreenWindowWidth,screenWindowHeight, 0x1, 6);mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);}

3. 横竖屏自动适配

回答:因为横竖屏状态下,采集的屏幕宽高不一样,如果横竖屏切换,这个时候,需要考虑到横竖屏适配问题,确保比如竖屏状态下,切换到横屏时,推拉流两端可以自动适配,横竖屏自动适配,编码器需要重启,拉流端,需要能自动适配宽高变化,自动播放。

4. 一定的补帧策略

回答:好多人不理解为什么要补帧,实际上,屏幕采集的时候,屏幕不动的话,不会一直有数据下去,这个时候,比较好的做法是,保存最后一帧数据,设定一定的补帧间隔,确保不会因为帧间距太大,导致播放端几秒都收不到数据,当然,如果服务器可以缓存GOP,这个问题迎刃而解。

5. 异常网络处理、事件回调机制

回答:如果是走RTMP,网络抖动或者其他网络异常,需要有好重连机制和状态回馈机制。

    class EventHandeV2 implements NTSmartEventCallbackV2 {@Overridepublic void onNTSmartEventCallbackV2(long handle, int id, long param1, long param2, String param3, String param4, Object param5) {Log.i(TAG, "EventHandeV2: handle=" + handle + " id:" + id);String publisher_event = "";switch (id) {case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_STARTED:publisher_event = "开始..";break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTING:publisher_event = "连接中..";break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTION_FAILED:publisher_event = "连接失败..";break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTED:publisher_event = "连接成功..";break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_DISCONNECTED:publisher_event = "连接断开..";break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_STOP:publisher_event = "关闭..";break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RECORDER_START_NEW_FILE:publisher_event = "开始一个新的录像文件 : " + param3;break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_ONE_RECORDER_FILE_FINISHED:publisher_event = "已生成一个录像文件 : " + param3;break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_SEND_DELAY:publisher_event = "发送时延: " + param1 + " 帧数:" + param2;break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CAPTURE_IMAGE:publisher_event = "快照: " + param1 + " 路径:" + param3;if (param1 == 0) {publisher_event = publisher_event + "截取快照成功..";} else {publisher_event = publisher_event + "截取快照失败..";}break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RTSP_URL:publisher_event = "RTSP服务URL: " + param3;break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUSH_RTSP_SERVER_RESPONSE_STATUS_CODE:publisher_event ="RTSP status code received, codeID: " + param1 + ", RTSP URL: " + param3;break;case NTSmartEventID.EVENT_DANIULIVE_ERC_PUSH_RTSP_SERVER_NOT_SUPPORT:publisher_event ="服务器不支持RTSP推送, 推送的RTSP URL: " + param3;break;}String str = "当前回调状态:" + publisher_event;Log.i(TAG, str);Message message = new Message();message.what = PUBLISHER_EVENT_MSG;message.obj = publisher_event;handler.sendMessage(message);}}

6. 部分屏幕数据采集

回答:我们遇到的好多场景下,教室端,会拿出来3/4的区域用来投递给学生看,1/4的区域,用来做一些指令等操作,这个时候,就需要考虑屏幕区域裁剪,接口可做如下设计:

	/*** 投递裁剪过的RGBA数据** @param data: RGBA data** @param rowStride: stride information** @param width: width** @param height: height** @param clipedLeft: 左;  clipedTop: 上; clipedwidth: 裁剪后的宽; clipedHeight: 裁剪后的高; 确保传下去裁剪后的宽、高均为偶数** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoClipedRGBAData(long handle,  ByteBuffer data, int rowStride, int width, int height, int clipedLeft, int clipedTop, int clipedWidth, int clipedHeight);
                        //实际裁剪比例,可酌情自行调整int left = 100;int cliped_left = 0;int top = 0;int cliped_top = 0;int cliped_width = width_;int cliped_height = height_;if(scale_rate == SCALE_RATE_HALF){cliped_left = left / 2;cliped_top = top / 2;//宽度裁剪后,展示3/4比例cliped_width = (width_ *3)/4;//高度不做裁剪cliped_height = height_;}else if(scale_rate == SCALE_RATE_TWO_FIFTHS){cliped_left = left * 2 / 5;cliped_top = top * 2 / 5;//宽度裁剪后,展示3/4比例cliped_width = (width_ *3)/4;//高度不做裁剪cliped_height = height_;}if(cliped_width % 2 != 0){cliped_width = cliped_width + 1;}if(cliped_height % 2 != 0){cliped_height = cliped_height + 1;}if ( (cliped_left + cliped_width) > width_){Log.e(TAG, " invalid cliped region settings, cliped_left: " + cliped_left + " cliped_width:" + cliped_width + " width:" + width_);return;}if ( (cliped_top + cliped_height) > height_){Log.e(TAG, "invalid cliped region settings, cliped_top: " + cliped_top + " cliped_height:" + cliped_height + " height:" + height_);return;}//Log.i(TAG, " clipLeft: " + cliped_left + " clipTop: " + cliped_top +  " clipWidth: " + cliped_width + " clipHeight: " + cliped_height);libPublisher.SmartPublisherOnCaptureVideoClipedRGBAData(publisherHandle, last_buffer, row_stride_,width_, height_, cliped_left, cliped_top, cliped_width, cliped_height );

7. 文字、图片水印

回答:好多场景下,同屏者会把公司logo,和一定的文字信息展示在推送端,这个时候,需要考虑到文字和图片水印问题,具体可参考如下接口设置:

   /*** Set Text water-mark(设置文字水印)* * @param fontSize: it should be "MEDIUM", "SMALL", "BIG"* * @param waterPostion: it should be "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT".* * @param xPading, yPading: the distance of the original picture.* * <pre> The interface is only used for setting font water-mark when publishing stream. </pre>  * * @return {0} if successful*/public native int SmartPublisherSetTextWatermark(long handle, String waterText, int isAppendTime, int fontSize, int waterPostion, int xPading, int yPading);/*** Set Text water-mark font file name(设置文字水印字体路径)** @param fontFileName:  font full file name, e.g: /system/fonts/DroidSansFallback.ttf** @return {0} if successful*/public native int SmartPublisherSetTextWatermarkFontFileName(long handle, String fontFileName);/*** Set picture water-mark(设置png图片水印)* 											* @param picPath: the picture working path, e.g: /sdcard/logo.png* * @param waterPostion: it should be "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT".* * @param picWidth, picHeight: picture width & height* * @param xPading, yPading: the distance of the original picture.* * <pre> The interface is only used for setting picture(logo) water-mark when publishing stream, with "*.png" format </pre>  * * @return {0} if successful*/public native int SmartPublisherSetPictureWatermark(long handle, String picPath, int waterPostion, int picWidth, int picHeight, int xPading, int yPading);

总结:其实一个好的同屏系统,需要考虑的地方远不止以上几点,比如编码参数策略等,都需要考量,后续有机会再和大家做进一步分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/553121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信公众号怎么给微店设置运费

微信小店想要设置运费&#xff0c;该怎么设置呢?今天我们就来看看使用微信公众号设置微店运费的教程。 1、在电脑登录你的微信公众号服务号&#xff0c;确保已经事先开通了微信小店功能 微信公众号怎么给微店设置运费? 2、点击左侧导航栏的微信小店&#xff0c;进去后点击…

RTSP/RTMP播放端录像不可忽视的几个设计要点

很多开发者提到&#xff0c;拉取的摄像机&#xff08;一般RTSP流&#xff09;或RTMP流&#xff0c;如果需要录制&#xff0c;需要考虑哪些因素&#xff0c;本文以大牛直播SDK的Windows平台拉流端录像为例&#xff08;github&#xff09;&#xff0c;做个简单的介绍&#xff1a;…

海康摄像机rtsp地址格式(官方最新版)

★目前海康录像机、网络摄像机&#xff0c;网络球机的RTSP单播取流格式如下&#xff08;车载录像机不支持RTSP取流&#xff09;&#xff1a; rtsp://用户名:密码IP:554/Streaming/Channels/101 →录像机示例&#xff1a; 取第1个通道的主码流预览 rtsp://admin:hik1234510.…

QQ邮箱怎么发送文件夹 怎样在QQ邮箱里发送压缩文件夹

有很多用户想要知道怎么样才能通过QQ邮箱来发送自己的一些文件压缩包&#xff0c;应该怎么操作呢?不要慌&#xff0c;现在小编就给大家分享一下&#xff0c;下面一起来学习操作步骤吧! 其实&#xff0c;无论何种邮箱都无法发送文件夹&#xff0c;都只能对文件进行操作。如果文…

时光手帐怎么修改作品 时光手帐修改作品封面方法

对于自己在时光手账Pro中的手账本封面是可以随时更改的。那么&#xff0c;怎么在时光手账Pro中更改自己手账封面?下面我使用苹果手机(安卓端操作方法一致)来分享一下具体的操作流程。 首先打开手机&#xff0c;点击进入时光手账Pro。 时光手帐怎么修改作品 时光手帐修改作品…

几款优秀的点播、RTSP/RTMP直播播放器介绍

1.ijkplayer 项目地址&#xff1a; https://github.com/Bilibili/ijkplayer 介绍&#xff1a;Ijkplayer 是Bilibili发布的基于 FFplay 的轻量级 Android/iOS 视频播放器。实现了跨平台功能&#xff0c;API 易于集成&#xff1b;编译配置可裁剪&#xff0c;方便控制安装包大小&…

Android平台RTMP推流或轻量级RTSP服务(摄像头或同屏)编码前数据接入类型总结

很多开发者在做Android平台RTMP推流或轻量级RTSP服务&#xff08;摄像头或同屏&#xff09;时&#xff0c;总感觉接口不够用&#xff0c;以大牛直播SDK为例 (Github) 我们来总结下&#xff0c;我们常规需要支持的编码前音视频数据有哪些类型&#xff1a; 1. Android摄像头前后…

作业帮口算批改怎么开 作业帮口算批改如何用

作业帮口算批改功能怎么用?作业帮最近全新改版的消息传的很火&#xff0c;新增了口算批改的功能&#xff0c;很吸引人。但是还有很多用户不是很清楚作业帮口算批改功能怎么用&#xff0c;下面是小编整理的关于作业帮口算批改功能怎么用的相关资讯&#xff0c;快来看看吧! 作业…

RTSP播放器或RTMP播放器常用的事件回调设计

很多开发者在开发RTSP或RTMP播放器的时候&#xff0c;不晓得哪些event回调事件是有意义的&#xff0c;针对此&#xff0c;我们以大牛直播SDK&#xff08;github&#xff09;的Android平台RTSP/RTMP直播播放端为例&#xff0c;简单介绍下常用的event id&#xff0c;总的来说&…

Windows平台RTMP多实例推送探讨

之前&#xff0c;我们博客 https://blog.csdn.net/renhui1112/article/details/105624392 提到&#xff0c;Android平台RTMP多实例推送的几种情况探讨&#xff0c;简单来说有以下三种情况&#xff1a; 多路编码&#xff0c;多个实例分别推送到不同的RTMP URL&#xff08;如And…

Win7蓝屏代码0x000000001e怎么解决

蓝屏问题&#xff0c;是所有系统都会遇到的最普遍的电脑故障问题&#xff0c;电脑蓝屏是因为系统与硬件或软件不兼容冲突引起的&#xff0c;不同的提示代码表示了不同的蓝屏原因&#xff0c;那么Win7蓝屏代码0x000000001e怎么解决?为此问题困扰的用户&#xff0c;请来看看Win7…

开发个好的RTMP播放器到底难在哪里?RTMP播放器对标和考察指标

好多开发者提到&#xff0c;RTMP播放器&#xff0c;不知道有哪些对标和考察指标&#xff0c;以下大概聊聊我们的一点经验&#xff0c;感兴趣的&#xff0c;可以关注 github&#xff1a; 1. 低延迟&#xff1a;大多数RTMP的播放都面向直播场景&#xff0c;如果延迟过大&#xf…

Android平台RTMP/RTSP播放器开发系列之解码和绘制

本文主要抛砖引玉&#xff0c;粗略介绍下Android平台RTMP/RTSP播放器中解码和绘制相关的部分(Github)。 解码 提到解码&#xff0c;大家都知道软硬解&#xff0c;甚至一些公司觉得硬解码已经足够通用&#xff0c;慢慢抛弃软解了&#xff0c;如果考虑到设备匹配&#xff0c;软…

Win7图片查看器打印不了图片怎么办

当我们想浏览电脑中的图片文件时&#xff0c;可以选择系统自带的图片查看器或者第三方看图工具打开&#xff0c;但是有些win7用户发现自己想通过windows图片查看器打印图片却没有反应&#xff0c;Win7图片查看器打印不了图片怎么办?就此剖&#xff0c;下面小编就来教教大家解决…

Android平台屏幕/摄像头或外部数据采集及RTMP推送接口设计描述

好多开发者提到&#xff0c;为什么大牛直播SDK的Android平台RTMP推送接口怎么这么多&#xff1f;不像一些开源或者商业RTMP推送一样&#xff0c;就几个接口&#xff0c;简单明了。 不解释&#xff0c;以Android平台RTMP推送模块常用接口&#xff0c;看看这些接口有没有存在的意…

钉钉怎么设置考勤打卡规则

1、首先在电脑上登陆钉钉后台&#xff0c;然后点击如图所示的钉钉考勤打卡 钉钉后怎么设置考勤打卡规则? 2、比如一个公司生产型企业 互联网部门上班时间是 周一到周五上班时间 8:30-5:30 周六上班 8:30-12:00 以此作为案例说明 钉钉后怎么设置考勤打卡规则? 3、首先设…

变废为宝:使用废旧手机实现实时监控方案

随着手机淘汰的速度越来越快&#xff0c;大多数手机功能性能很强劲就不再使用了&#xff0c;以大牛直播SDK现有方案为例&#xff0c;本文探讨下&#xff0c;如何用废旧手机实现实时监控方案&#xff08;把手机当摄像头做监控之用&#xff09;&#xff1a; 本方案需要准备一个手…

企业微信登录不了怎么办 企业微信无法登录的原因及解决方法

企业微信无法登陆怎么办?企业微信为什么登陆不了?应该怎么解决?企业微信一个很好用的基础办公沟通工具&#xff0c;现在很多朋友都在使用。那么&#xff0c;如果遇到企业微信登不上的情况应该怎么办呢?接下来小编就给大家带来企业微信无法登录的原因及解决方法&#xff0c;…

RTSP鉴权认证之基础认证和摘要认证

RTSP认证类型 基本认证&#xff08;basic authentication&#xff09;&#xff1a;http 1.0提出的认证方案&#xff0c;其消息传输不经过加密转换因此存在严重的安全隐患&#xff1b;摘要认证&#xff08;digest authentication&#xff09;&#xff1a;http 1.1提出的基本认证…

播放器之争:VLC VS SmartPlayer

好多开发者跟我们交流的时候提到&#xff0c;为什么有了VLC这种开源播放器&#xff0c;大牛直播SDK还要开发SmartPlayer&#xff1f;以下就针对VLC和SmartPlayer功能支持和涉及侧重&#xff0c;做个大概的比较&#xff1a; VLC VLC的全名是Video Lan Client&#xff0c;是一个…