Linphone探索:7 . 如何进行视频电话

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本身就有的组件,我们直接哪来就用了。这个组件自动的将本地摄像头的头像投射到了小窗口,对方视频的图像经过界面投射到了大窗口上。
就是这个文件:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用户点击 用户点击 linphone linphone linphone linphone 的图标后就开始了 的图标后就开始了 的图标后就开始了 的图标后就开始了 的图标后就开始了 linphone linphone linphone linphone 软件,这时 软件,这时 软件,这时 软件,这时 软件,这时 linphoneActivity linphoneActivity linphoneActivity linphoneActivity linphoneActivity linphoneActivity linphoneActivity开始运行,它 开始运行,它 开始运行,它 开始运行,它 使 linphoneService linphoneService linphoneService linphoneService linphoneServicelinphoneServicelinphoneService 开始,并做一些 开始,并做一些 开始,并做一些 开始,并做一些 linphone linphone linphone linphone 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 帐号密码的登录操作同时引导用户进行环境变 量的设置( 量的设置( LinphonePreferencesActivity LinphonePreferencesActivity LinphonePreferencesActivityLinphonePreferencesActivity LinphonePreferencesActivityLinphonePreferencesActivityLinphonePreferencesActivityLinphonePreferencesActivity LinphonePreferencesActivity LinphonePreferencesActivity LinphonePreferencesActivity LinphonePreferencesActivity)。 环境变量都储存在 环境变量都储存在 环境变量都储存在 环境变量都储存在 sharedPreferencessharedPreferences sharedPreferencessharedPreferences sharedPreferencessharedPreferencessharedPreferencessharedPreferences sharedPreferences 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 中,它是整个工程共享的一变量池。这些环境有 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自动启回校正网络 音频和视编码设置选择,帐号密服务器自
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值