AnyChat SDK的使用及简易视频聊天软件的快速开发(QT5.3)

为了在linux平台下快速开发一款视频聊天软件,本文选取了AnyChat SDK作为核心开发,开发环境使用QT5.3,下面将讲解我的开发过程。

 

一、 开发环境的搭建

1. 首先,虚拟机安装linux系统,我选取的是最新的Ubuntu14.04-32bit ;

2. 然后,到QT官网http://qt-project.org/downloads,下载最新的linux版本QT5.3.2,如下所示:

 

聊天软件高并发架构_音视频开发

3. 最后,到AnyChat官网http://www.anychat.cn/download.html,下载最新的linux版本的SDK,这里我们选取32bit,如下图所示:

 

聊天软件高并发架构_视频聊天_02

二、 软件功能

在这里,我只需要如下几个功能即可:

1. 能够打开本地音视频;

2. 能够获取在线用户列表;

3. 能够请求在线用户音视频,实现视频聊天;

4. 能够发送文字聊天。

 

三、 真正的开始

需求确定之后,我们就开始创建我们的工程啦!

1. 现在我们打开QT5软件,创建一个新工程,首先就是布局我们的UI,如下图所示;

聊天软件高并发架构_视频聊天_03

然后我们给我们的UI写上对象名字,如下所示:

 

聊天软件高并发架构_视频开发技术_04

2. 添加工程依赖性(包括anychat sdk依赖文件的添加)

QT软件配置头文件和库文件有两种方法:

2.1 可以手动在.pro为后缀的文件里面进行添加;

2.2 可以右键工程项目,然后添加相应的文件和库,此方法会自动修改.pro文件,如下左右两图所示(左图为手动添加,右图为添加后的pro文件,也可以按右图修改pro文件):

 

聊天软件高并发架构_聊天软件高并发架构_05

聊天软件高并发架构_视频开发技术_06

其中INCLUDEPATH为头文件包含路径,这里添加anychat sdk目录;LIBS为依赖库文件,这里添加anychatcore动态库;$$PWD表示pro文件当前目录;当然也可以使用绝对路径,直接填写路径和文件名即可,按左图方法添加绝对正确。

我的anychat sdk文件如下所示:

 

聊天软件高并发架构_视频聊天_07

 

3. 接下来我们需要编写具体功能的实现;

3.1 初始化

因为我们要使用anychat sdk,因此我们在程序初始化的时候对sdk初始化;

SDK初始化参数设置,其中,对于视频,我们设置为BRAC_FUNC_VIDEO_CBDATA,为视频数据回调方式,后续需要我们实现视频数据的处理,这里主要是渲染显示;对于音频,我们设置为BRAC_FUNC_AUDIO_AUTOPLAY,使用SDK自动播放模式,我们不用做任何处理。


聊天软件高并发架构_聊天软件高并发架构_08

在BRAC_InitSDK函数之后我们又调用了四个API接口,分别设置视频回调、声音回调(这里实际不用设置,我们采用自动播放模式)、系统消息回调、文字信息回调(文字聊天);

至此初始化完毕!

3.2 编写登录服务器接口

聊天软件高并发架构_视频聊天_09

这里为了方便,服务器地址、端口号、用户名、密码都写进来了;当我们登录成功之后,就可以继续往下啦。

聊天软件高并发架构_即时通讯软件_10

3.3 进入相应的房间

RoomId_lineEdit就是我们的ui控件,我们在编辑控件填写相应的房号即可;

3.4 刷新在线用户列表

聊天软件高并发架构_聊天软件高并发架构_11

我单独写了一个接口,实现由用户进入房间和离开房间时会刷新列表;

 

3.5 打开本地音视频

当我们成功进入房间时,我们首先打开自己的音视频,这里用到了两个API,

聊天软件高并发架构_视频开发技术_12

BRAC_UserCameraControl()和BRAC_UserSpeakControl(),分别打开音视频;

 

这个函数有系统消息回调函数来调用,而系统消息回调函数我们在初始化的时候已经设置了,下面将我们的系统消息回调函数贴出来:

 

// 异步消息通知回调函数定义

void CALLBACK Widget::NotifyMessage_CallBack(DWORD dwNotifyMsg, DWORD wParam, DWORD lParam, LPVOID lpUserValue)

{

    Widget* pAnyChatSDKProc = (Widget*)lpUserValue;

    if(!pAnyChatSDKProc)

                return;

    switch(dwNotifyMsg)

    {

   case WM_GV_CONNECT:      pAnyChatSDKProc->OnGVClientConnect(wParam,NULL);         

     break;

   case WM_GV_LOGINSYSTEM:      pAnyChatSDKProc->OnGVClientLogin(wParam,lParam);               

     break;

   case WM_GV_ENTERROOM:       pAnyChatSDKProc->OnGVClientEnterRoom(wParam,lParam);          

     break;

   case WM_GV_MICSTATECHANGE: pAnyChatSDKProc->OnGVClientMicStateChange(wParam,lParam);  

break;

   case WM_GV_USERATROOM:      pAnyChatSDKProc->OnGVClientUserAtRoom(wParam,lParam);           

     break;

   case WM_GV_LINKCLOSE:         pAnyChatSDKProc->OnGVClientLinkClose(wParam, lParam);              

     break;

   case WM_GV_ONLINEUSER:      pAnyChatSDKProc->OnGVClientOnlineUser(wParam,lParam);            

     break;

 

  case WM_GV_CAMERASTATE:      pAnyChatSDKProc->OnAnyChatCameraStateChgMessage(wParam,lParam);                              break;

  case WM_GV_ACTIVESTATE:         pAnyChatSDKProc->OnAnyChatActiveStateChgMessage(wParam,lParam);  

      break;

  case WM_GV_P2PCONNECTSTATE: pAnyChatSDKProc->OnAnyChatP2PConnectStateMessage(wParam,lParam);    break;

  case WM_GV_SDKWARNING:       pAnyChatSDKProc->OnAnyChatSDKWarningMessage(wParam,lParam);         break;

        default:

                break;

        }

        pAnyChatSDKProc->OnAnyChatNotifyMessageCallBack(dwNotifyMsg,wParam,lParam);

};


3.6 请求在线用户视频

我们进入房间后,获取在线用户并更新列表,所谓的在线用户是指同一房间的在线用户。

聊天软件高并发架构_即时通讯软件_13

然后我们双击列表中的用户,进行视频请求:

 

聊天软件高并发架构_音视频开发_14

我的虚拟机中打不开本地视频,所以左下角没有视频,具体的实现如下:

其中g_sOpenedCamUserId为全局变量,用于保存被请求视频的用户名;

聊天软件高并发架构_音视频开发_15

音视频成功啦,接下来我们继续扩展文字消息。

 

视频控制

音频控制

 

以上两个函数说明,参数1为用户id值,这个不难理解,参数2为打开和关闭控制值,建议使用true或false;在我实际开发过程中,在音视频关闭的时候,参数2设置为-1的时候,结果没有关闭成功,因为理解有误,应该设置为0。

 

聊天软件高并发架构_视频聊天_16

3.7 实现发送文字消息聊天

BARC_SendTextMessage即可啦,参数一为用户id,至此,我们的功能基本完成;

3.8 有进必有出---离开房间

离开房间之后可以做什么?我们考虑实现离开房间后,要进入其他房间而不马上退出,因此这里我只使用了LeaveRoom!!!

当然我们离开后需要关闭视频和刷新列表,对于关闭视频调用关闭音视频接口,然后设置ui-->clear和text,对于列表,调用封装好的接口即可;

 

聊天软件高并发架构_音视频开发_17

3.9 关键的视频渲染

因为我使用了回调方式获取视频数据,所以我得手动进行视频渲染首先定义视频缓冲和大小(我这里定义为类成员):


聊天软件高并发架构_聊天软件高并发架构_18

然后在回调函数中做视频渲染:

QT中我使用QImage来加载视频数据,然后调用label控件的setPixmap方法来绘制图像,当然这个渲染方法效率一般;

//视频数据显示
void Widget::DrawUserVideo(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, 
                        BITMAPINFOHEADER bmiHeader,Widget *pWidget)
{
    int width  =  bmiHeader.biWidth;
    int height  =  bmiHeader.biHeight;
 
判断用户id选择不同的显示区域
本地用户视频
    {
        char* p = m_lpLocalVideoFrame;
        if(  !p ||m_iLocalVideoSize < dwLen)
        {
            p = (char*)realloc(p, dwLen);
            if(!p)
                return;
            m_iLocalVideoSize = dwLen;
        }
        memcpy(p, lpBuf, dwLen);
        QImage img = QImage((uchar *)p,width,height,QImage::Format_RGB32);
        pWidget->ui->RemoteUserlabel->setPixmap(QPixmap::fromImage(img));
    }
远程用户视频
    {
        char* p = m_lpRemoteVideoFrame;
        if(  !p ||m_iRemoteVideoSize < dwLen)
        {
            p = (char*)realloc(p, dwLen);
            if(!p)
                return;
            m_iRemoteVideoSize = dwLen;
        }
        memcpy(p, lpBuf, dwLen);
        QImage img = QImage((uchar *)p,width,height,QImage::Format_RGB32);
        pWidget->ui->RemoteUserlabel->setPixmap(QPixmap::fromImage(img));
    }
}

3.10 

最后,我没有添加关闭按钮,而是使用窗口的关闭按钮,所以我要重载CloseEvent,在关闭时调用断开连接和释放资源。

 

聊天软件高并发架构_聊天软件高并发架构_19

四、 总结

AnyChat SDK接口的使用简洁,尤其是音视频打开和处理过程的简化,全面的回调功能函数接口。本设计采用服务器为anychat sdk提供的demo服务器,可以直接运行部署。