视频聊天软件的快速开发(QT5.3)

来源:互联网 发布:淘宝如何优化宝贝 编辑:程序博客网 时间:2024/05/24 06:36

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,如下图所示:

 

二、 软件功能

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

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

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

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

4. 能够发送文字聊天。

 

三、 真正的开始

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

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

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

 

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

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

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

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

 

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

我的anychat sdk文件如下所示:

 

 

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

3.1 初始化

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

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

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

至此初始化完毕!

3.2 编写登录服务器接口


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


3.3 进入相应的房间

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

3.4 刷新在线用户列表


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

 

3.5 打开本地音视频

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


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 请求在线用户视频

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


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

 

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

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


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

 

        BRAC_UserCameraControl(g_sOpenedCamUserId,0);   //视频控制

        BRAC_UserSpeakControl(g_sOpenedCamUserId,0);     //音频控制

 

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

 

3.7 实现发送文字消息聊天

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

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

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

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

 

3.9 关键的视频渲染

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

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

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选择不同的显示区域

    if(m_SelfId == dwUserid) //本地用户视频

    {

        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));

    }

    else  //远程用户视频

    {

        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在关闭时调用断开连接和释放资源。

 

四、 总结

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


0 0
原创粉丝点击