Linphone探索:7 . 如何进行视频电话
来源:互联网 发布:原油api数据影响 编辑:程序博客网 时间:2024/04/30 18:59
1 . 绪论
本月还有3篇微博需要更新,否则就持之以恒的徽章就没啦,前一段时间都在忙各种事情没有时间更新博客,现在阶段性的不太忙了,补上这月个剩下的3篇,关于Linphone的内容,各位有想了解的,想好题目,在留言你提问,如果我能解答我就出个博客专门说一下,解答不了的也没辙了。
本博客的大部分内容是为了记录项目中的一些和业务不太相关,但是和对应技术比较相关的东西,一方面为了以后能回顾一下,另一方面也能帮其它同学解决点实际问题。
- 整体思路
服务器支持。
终端设置。
拨出视频电话。
接听视频电话
显示双向视频。
- 分步实现
3.1 服务器支持
我使用的服务器是Freeswitch,需要在服务器上设置视频对应的编码方式。
已下配置来自于《FreeSWITCH权威指南》:
freeswitch模式支持语音通话,因此默认的通话皆为语音通话,如果需要支持视频通话,只需要在配置文件中增加想关的视频编解码就可以了。
freeswitch目前支持的编解码方式有:H261、H263、H264、VP8等。
freeswitch只支持视频透传,所以必须电话两侧的终端都为同一种编码方式。
在conf/vars.xml中修改如下
<X-PRE-PROCESS cmd="set" data="global_codec_prefs=G722,PCMU,PCMA,GSM"/> <X-PRE-PROCESS cmd="set" data="outbound_codec_prefs=PCMU,PCMA,GSM"/> 改为 <X-PRE-PROCESS cmd="set" data="global_codec_prefs=G722,PCMU,PCMA,GSM,H263,H264,VP8"/> <X-PRE-PROCESS cmd="set" data="outbound_codec_prefs=PCMU,PCMA,GSM,H263,H264,VP8"/>
重启服务器,使配置生效
使用sofia status profile internal 查看视频编码方式是否成功配置
3.2 终端设置
前提为设备成功启动Linphone service,此时LinphoneCore,LinphoneManager,LinphonePreferences 都已经正常启动。
使用如下代码配置终端参数
/*获得LinphonePreferences的实体类,这个包含了Linphone的所有参数配置*/LinphonePreferences mPrefs = LinphonePreferences.instance();/*设置自动接听视频通话的请求,也就是说只要是视频通话来了,直接就接通,不用按键确定,这是我们的业务流,不用理会*/mPrefs.setAutomaticallyAcceptVideoRequests(true);/*设置初始话视频电话,设置了这个你拨号的时候就默认为使用视频发起通话了*/mPrefs.setInitiateVideoCall(true);/*这是允许视频通话,这个选了false就彻底不能接听或者拨打视频电话了*/mPrefs.enableVideo(true);setCodecMime();/* 设置音频的codec,这里我只选择了打开VP8的codec。H264因为硬件平台的原因,无法正常使用decode所以放弃了*/private void setCodecMime(){ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); for (final PayloadType pt : lc.getVideoCodecs()) { debug.i("setCodecMime = " + pt.getMime()); if (!pt.getMime().equals("VP8")) { try { debug.i("disable codec " + pt.getMime()); LinphoneManager.getLcIfManagerNotDestroyedOrNull().enablePayloadType(pt, false); } catch (LinphoneCoreException e) { Log.e(e); } } }}
3.3 拨出视频电话
实际上在完成了上述设置后,若对方也打开了视频通话的选项,并且选定了编码方式为VP8后,只要调用拨号的API即可实现拨出视频电话。
使用如下方法即可实现上述功能。
public static void dialNumber(String number){ if (LinphoneManager.getLc().getCallsNb() == 0) { debug.i("dialNumber(" + number + ");"); LinphoneManager.getInstance().newOutgoingCall("电话号码", "显示姓名"); }}
3.4 接听视频电话
在通话到来时,也就是在callState变成IncomingReceived时,调用answer方法即可实现视频接听。
public static void answer(Context mContext){ if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) { List<LinphoneCall> calls = LinphoneUtils.getLinphoneCalls(LinphoneManager.getLc()); for (LinphoneCall call : calls) { if (State.IncomingReceived == call.getState()) { mCall = call; break; } } } if (State.IncomingReceived != mCall.getState()) return; if (mContext.getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance() .audioPermAsked()) { // startActivity(new Intent(LinphoneActivity.instance(), // CallIncomingActivity.class)); debug.i("CallIncomingActivity.class"); } else { debug.i("checkAndRequestAudioPermission(true);"); checkAndRequestAudioPermission(mContext, true); } LinphoneCallParams params = LinphoneManager.getLc().createCallParams(mCall); boolean isLowBandwidthConnection = !LinphoneUtils.isHighBandwidthConnection(LinphoneService.instance().getApplicationContext()); if (params != null) { params.enableLowBandwidth(isLowBandwidthConnection); } else { Log.e("Could not create call params for call"); } if (params == null || !LinphoneManager.getInstance().acceptCallWithParams(mCall, params)) { // the above method takes care of Samsung Galaxy S // Toast.makeText(this, R.string.couldnt_accept_call, // Toast.LENGTH_LONG).show(); } else { // if (!LinphoneActivity.isInstanciated()) { // return; // } final LinphoneCallParams remoteParams = mCall.getRemoteParams(); if (remoteParams != null && remoteParams.getVideoEnabled() && LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) { // LinphoneActivity.instance().startVideoActivity(mCall); debug.i("LinphoneActivity.instance().startVideoActivity(mCall)"); switchVideo(true); } else { debug.i("LinphoneActivity.instance().startIncallActivity(mCall);"); // LinphoneActivity.instance().startIncallActivity(mCall); switchVideo(false); } }}private static void switchVideo(final boolean displayVideo){ debug.i("switchVideo"); final LinphoneCall call = LinphoneManager.getLc().getCurrentCall(); if (call == null) { return; } // Check if the call is not terminated if (call.getState() == State.CallEnd || call.getState() == State.CallReleased) return; if (!displayVideo) { // showAudioView(); } else { if (!call.getRemoteParams().isLowBandwidthEnabled()) { LinphoneManager.getInstance().addVideo(); debug.i("addVideo"); // if (videoCallFragment == null || // !videoCallFragment.isVisible()) // { // showVideoView(); // } } else { // displayCustomToast(getString(R.string.error_low_bandwidth), // Toast.LENGTH_LONG); } }}
上面的代码已经屏蔽了所有的页面跳转的代码。其间比较关键的是在switchVideo方法中的如下部分
if (!call.getRemoteParams().isLowBandwidthEnabled()){ LinphoneManager.getInstance().addVideo(); debug.i("addVideo"); // if (videoCallFragment == null || // !videoCallFragment.isVisible()) // { // showVideoView(); // }}
这里在查看了当前带宽时候能够支持视频通话后,执行LinphoneManager.getInstance().addVideo();添加了视频。
3.4 显示双向视频
在主程序界面放置一个fragment控件。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@+drawable/background" android:gravity="center_horizontal" tools:context="com.sxkeda.launcher.MainActivity" tools:ignore="MergeRootFrame" > <LinearLayout android:id="@+id/fragmentContainer2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_below="@+id/titleBar" android:layout_toRightOf="@+id/left_icon_panel" android:orientation="vertical" > </LinearLayout></RelativeLayout>
在电话状态LinphoneCall.State 等于 Connected(接通)和OutgoingProgress(拨出电话)时。在主程序中替换fragment组件。
if (state == LinphoneCall.State.Connected){ LinphoneCall mCall = LinphoneManager.getLc().getCurrentCall(); /*在接通状态下,必须查看来电的远程参数,确定其带有视频通话的参数才打开视频通话,否则只进行语音通话*/ final LinphoneCallParams remoteParams = mCall.getRemoteParams(); debug.i("remoteParams.getVideoEnabled() = "+remoteParams.getVideoEnabled()); if (remoteParams != null && remoteParams.getVideoEnabled()) { changeFragmentToVideoCall(); } else { changeFragmentToAudioCall(); }}if (state == LinphoneCall.State.OutgoingProgress){ debug.i("to CallVideoFragment"); if (Business.getInstance().isCurrentCallVideo()) { changeFragmentToVideoCall(); } else { changeFragmentToAudioCall(); }} private void changeFragmentToVideoCall(){ CallVideoFragment videoCallFragment = new CallVideoFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragmentContainer2, videoCallFragment); transaction.commit();}
在切换视频的时候,我们使用了一个fragment为CallVideoFragment,这个组件是Linphone本身就有的组件,我们直接哪来就用了。这个组件自动的将本地摄像头的头像投射到了小窗口,对方视频的图像经过界面投射到了大窗口上。
就是这个文件:
- Linphone探索:7 . 如何进行视频电话
- Linphone探索:7 . 如何进行视频电话
- linphone-自动接听视频电话
- 开源sip电话 linphone
- Linphone 拨打电话流程
- Linphone 拨打电话流程
- linphone-linphone视频时退到后台如何返回到视频界面
- Linphone探索:3 . LinphoneService
- Linphone探索:1 . Linphone官方源码探究
- Linphone探索:2 . linphone-android 业务流程
- Linphone探索:5 . Linphone配置大全
- Linphone探索:6 . Linphone用户注册
- Linphone探索:4 . 专有名词解释
- MTK65XX如何去掉视频电话功能
- 如何进行视频推广
- linphone 移植console 视频功能
- 如何利用Watson Analytics进行数据探索
- 育贤小贴士教您如何进行视频推广
- Log记录的日志的方法
- C++中的重载、隐藏和重写
- yii 操作session
- Linux系统编程2.文件
- sort()方法详解
- Linphone探索:7 . 如何进行视频电话
- jQuery 自定义选择器及应用
- activity的4种启动模式
- js数组与字符串的相互转化
- [机器学习]机器学习笔记整理05-决策树
- 最大比例
- oracle11g的安装中遇到未找到文件wfmlrsvcapp.ear报错
- Halcon串口配置
- android源码下载