本文介绍的多路投屏直播,主要是智能交互会议、多人同时投屏的应用场景,但不限于此。现实生活中,早已经出现多路视频监控的应用领域。为了提高开会沟通效率,多人协同、多路投屏互动的场景应运而生。会议投屏对实时性要求非常高,目前可以做到1080P的视频流直播延时130ms左右,比游戏直播、主播直播的延时要求高很多。因此,需要基于IjkPlayer做二次修改,从缓冲队列、解码耗时、渲染队列三个方面优化。

关联文章:

RTSP直播延时的深度优化

从FFmpeg源码去解决IJKPlayer直播花屏问题

1、页面布局

采用水平、垂直两条分割线把整个画面分割为四画面,四个通道分别对应一个IjkVideoView。

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><Viewandroid:id="@+id/divider1"android:layout_width="match_parent"android:layout_height="1dp"android:background="@color/ijk_color_blue_800"android:layout_centerVertical="true"/><Viewandroid:id="@+id/divider2"android:layout_width="1dp"android:layout_height="match_parent"android:background="@color/ijk_color_blue_800"android:layout_centerHorizontal="true"/><com.frank.living.widget.IjkVideoViewandroid:id="@+id/video_view1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@+id/divider1"android:layout_toStartOf="@id/divider2"/><com.frank.living.widget.IjkVideoViewandroid:id="@+id/video_view2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@+id/divider1"android:layout_toEndOf="@id/divider2"/><com.frank.living.widget.IjkVideoViewandroid:id="@+id/video_view3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/divider1"android:layout_toStartOf="@id/divider2"/><com.frank.living.widget.IjkVideoViewandroid:id="@+id/video_view4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/divider1"android:layout_toEndOf="@id/divider2"/></RelativeLayout>

2、初始化播放器参数

IjkPlayer播放器的参数分为:PLAYER、FORMAT、CODEC、SWS四大类。包括探测数据包数量、分析码流时长、TCP/UDP连接、环路滤波、网络卡顿丢帧、硬解码配置、缓冲区大小设置等等。

private void setOptions(IjkMediaPlayer ijkPlayer){if (ijkPlayer == null)return;ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "fast", 1);//不额外优化ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 200);ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);//是否开启缓冲ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1);//0:代表关闭,1:代表开启ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);//开启硬解ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);//自动旋屏ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 0);//处理分辨率变化ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 0);//最大缓存数ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 2);//默认最小帧数2ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 30);//最大缓存时长ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);//是否限制输入缓存数ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "nobuffer");//设置播放前的最大探测时间,分析码流时长:默认1024*1000ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzedmaxduration", 100);//ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");//tcp传输数据
}

3、初始化播放器

创建播放器,并初始化。单路投屏时,我们默认为全屏显示。

private void setupView(){//第一路投屏默认全屏enterFullScreen(1);mVideoView1.setVideoPath(url);mVideoView1.setIjkPlayerListener(new IjkPlayerListener() {@Overridepublic void onIjkPlayer(IjkMediaPlayer ijkMediaPlayer) {//设置播放器optionsetOptions(ijkMediaPlayer);}});mVideoView1.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(IMediaPlayer iMediaPlayer) {ijkPlayer = iMediaPlayer;}});mVideoView1.start();
}

4、投屏通道处理

我们使用HashMap来保存投屏客户端ip与通道数对应关系,另外使用TreeMap来记录每个通道投屏状态。

//四分屏模式还是全屏模式
private boolean isMultiScreen;
//保存客户端ip与通道数对应关系
private HashMap<String, Integer> clientMap = new HashMap<>();
//记录每个通道的投屏状态
private TreeMap<Integer, Boolean> channelMap = new TreeMap<>();

5、增加投屏

在接收到增加投屏广播后,选择空闲通道来投屏。需要特别注意的是,当第二路来投屏时,自动把全屏切换为多屏模式。

  int clientNum = intent.getIntExtra("clientNum", 0);String otherUrl = intent.getStringExtra("url");String ipAddress = intent.getStringExtra("ip");//选择空闲通道int channel = selectIdleChannel(clientNum);clientMap.put(ipAddress, channel);channelMap.put(channel, true);addClient(channel, otherUrl);//单屏变为两路投屏时,自动切换为多屏模式if (clientNum == 2){exitFullScreen();}
/*** 选择空闲通道* @param clientNum clientNum* @return idleChannel*/
private int selectIdleChannel(int clientNum){for (int channel = 1; channel < clientNum; channel++){if (!channelMap.get(channel)){return channel;}}return clientNum;
}

6、移除投屏

当接收到移除投屏广播后,根据待移除客户端的ip地址,从HashMap遍历找到需要移除的客户端。如果当前投屏总数是两路,移除其中一路后,剩下最后一路投屏自动切换为全屏。

int num = intent.getIntExtra("clientNum", 0);
if (num == 0){Process.killProcess(Process.myPid());
}else if (num > 0){String ipAddress = intent.getStringExtra("ipAddress");int target = clientMap.get(ipAddress);removeClient(target);clientMap.remove(ipAddress);channelMap.put(target, false);//多屏变为单屏时,自动切换为全屏if (num == 1){int castingChannel = getCastingChannel();enterFullScreen(castingChannel);}
}

7、全屏与分屏切换

双击某路投屏通道时,实现全屏与多屏的互相切换。

/*** 进入全屏模式* @param channel channel*/
private void enterFullScreen(int channel){hideDivider();switch (channel){case 1:mVideoView1.setVisibility(View.VISIBLE);mVideoView2.setVisibility(View.GONE);mVideoView3.setVisibility(View.GONE);mVideoView4.setVisibility(View.GONE);break;case 2:mVideoView1.setVisibility(View.GONE);mVideoView2.setVisibility(View.VISIBLE);mVideoView3.setVisibility(View.GONE);mVideoView4.setVisibility(View.GONE);break;case 3:mVideoView1.setVisibility(View.GONE);mVideoView2.setVisibility(View.GONE);mVideoView3.setVisibility(View.VISIBLE);mVideoView4.setVisibility(View.GONE);break;case 4:mVideoView1.setVisibility(View.GONE);mVideoView2.setVisibility(View.GONE);mVideoView3.setVisibility(View.GONE);mVideoView4.setVisibility(View.VISIBLE);break;default:break;}
}
/*** 退出全屏模式*/
private void exitFullScreen(){showDivider();mVideoView1.setVisibility(View.VISIBLE);mVideoView2.setVisibility(View.VISIBLE);mVideoView3.setVisibility(View.VISIBLE);mVideoView4.setVisibility(View.VISIBLE);
}

通过标志位来记录当前是全屏模式还是分屏模式,再根据标志位来切换全屏/分屏。

/*** 切换分屏模式* @param channel channel*/
private void changeScreenMode(int channel){isMultiScreen = !isMultiScreen;if (isMultiScreen){enterFullScreen(channel);}else {exitFullScreen();}
}

至此,可以实现多路投屏直播的基本功能。等待5G时代到来,多屏互动会更加成熟,逐渐走入现实生活。

基于IjkPlayer的多路投屏直播相关推荐

  1. mac 电脑连接不上github_Mac版爱思助手【手机投屏直播】工具使用教程

    Mac版爱思助手[手机投屏直播]是专门为Mac直播平台主播用户打造的全民直播工具,直播平台主播将苹果手机或其他苹果移动设备连接i4AirPlayer后,可将设备上的画面投屏到Mac电脑上进行直播. M ...

  2. java投屏刺激战场_吃鸡手游直播教程,怎么投屏直播玩刺激战场/全军出击

    吃鸡手游直播教程,怎么投屏直播玩刺激战场/全军出击 作者:小葫芦直播管家 来源:小葫芦 时间:2018-05-15 15:57 "吃鸡"游戏火热,尤其是刺激战场和全军出击这两款手机 ...

  3. ADB投屏_知乎安卓手游投屏直播教程

    最近 @小直同学 推出了新的直播活动(主播激励计划): 小直同学:「王者荣耀」主播激励计划,报名开始啦!​zhuanlan.zhihu.com 而知乎的直播系统还处于刚起步状态,整体的直播体系还有很大 ...

  4. 最简单的免费安卓手机投屏电脑游戏直播工具推荐:电脑控制手机玩游戏了解一下

    安卓投屏电脑的工具哪些比较好用?有哪些免费的手机投屏直播软件?什么投屏工具可以传输声音?市面上的安卓投屏工具非常多,效果和可实现的功能却不同,收费的免费的都有,今天良心介绍几款我直播游戏用过的比较好用 ...

  5. 安卓手机投屏软件_直播教程 | 安卓手机投屏队伍语音解决方案1

    安卓手机投屏队伍语音解决方案1 主播大大好啊! 我们之前的文章讲过安卓手机投屏到直播电脑的手游直播教程,使用台式机+投屏的方式,这样无论是游戏体验,还是直播的观看体验,都会好很多,这是也是被手游主播普 ...

  6. android手游直播怎么推流,安卓手机直播,Total Control手游投屏教程

    安卓手机直播,Total Control手游投屏教程 作者:小葫芦直播管家 来源:小葫芦 时间:2018-04-27 10:57 手游主播们,安卓手机投屏直播,你们都学会了吗? 是时候表演真正的技术了 ...

  7. android直播怎么投屏,安卓手机怎么直播,Total Control手游投屏教程

    安卓手机怎么直播,Total Control手游投屏教程 手游主播们,安卓手机投屏直播,你们都学会了吗? 要想在电脑上直播玩手游,需要使用投屏软件将手机画面投屏到直播工具,然后开始直播. 安卓手机目前 ...

  8. 用tcgames快速投屏方式进行刺激战场手游安卓直播投屏详细教程

    安卓手机直播手游怎么投屏?搞直播的都知道在直播手游的时候首先需要把手机用投屏工具投屏在电脑上,再配合直播推流工具如OBS.小葫芦或虎牙.斗鱼等自带的直播推流才能进行手游直播.苹果手机自带投屏,安卓手机 ...

  9. 这恐怕是目前画质最好最流畅的安卓直播投屏软件了

    直播投屏软件哪块最好用无延迟?现在市面上的安卓投屏软件比较多,但是很多延迟比较大,直播的时候用起来非常不爽.最近玩吃鸡的时候发现一个神器非常好用,虽然它主打不爽投屏,但是原理也是把手机投屏到电脑上然后 ...

最新文章

  1. [WCF] - Odata Service 访问失败,查看具体错误信息的方法
  2. 【HDU】2087 剪花布条 (KMP算法的应用)
  3. Windows App开发之集成设置、帮助、搜索和共享
  4. php读程序,PHP 读取大文件程序代码
  5. android inset 标签,android – 有几个WindowInsets?
  6. Magento数据库结构:EAV
  7. SQL SERVER2008 存储过程、表、视图、函数的权限
  8. freecplus框架,Linux平台下C/C++程序员提高开发效率的利器
  9. 15. 从远程库克隆
  10. 在html中如何写日期的代码,日期html代码
  11. java 图像锐化_Java中图像锐化操作的方法详解
  12. Ubuntu | ubuntu下安装edge
  13. 洛谷刷题笔记 乘方计算
  14. 研究生学术道德考试 部分题目 Word可搜索版
  15. 待办-9月7号-11号(month9week2)
  16. 微信公众号官网平台与微信公众号第三方平台的区别
  17. POI动态导出多层表头的EXCEL文件
  18. 基于springboot+bboss整合的elasticsearch(好用的一匹)
  19. 校招----青颖飞帆二面面经
  20. 【笔试】京东数据分析暑期实习

热门文章

  1. (二)textarea中placeholder不显示
  2. Android 6.0 Marshmallow
  3. 3D游戏引擎架构设计基础 - 学堂在线慕课习题答案
  4. 基于springboot+dubbo微服务开发的商城系统
  5. 单片机中动态数码管闪烁问题
  6. 跳槽字节跳动,从新手到Flutter架构师,一篇就够!深度好文
  7. 移动端设置overflow-x:hiden后scrollTop失效并一直为0
  8. chrome浏览器解除网页右键点击屏蔽方法
  9. 48个英语音标练习-海伦英语视频
  10. 一体化伺服电机一圈多少脉冲