zoukankan      html  css  js  c++  java
  • 音视频即时通讯的基本开发流程

    面对现在的即时通讯应用软件的崛起,很多开发者也是竭尽所能在这方面进行研究和学习!今天我在这里介绍一款音视频即时通讯的开发流程。

    下面列出AnyChat Platform Core SDK基本开发流程,适用于开发视频会议系统、语音视频聊天系统、远程教育平台以及即时通讯平台(IM)等。

    一、初始化

    该部分是首先要完成的,用于设置SDK的一些行为,包括设置对应的回调函数、设置SDK组件路径、设置是否产生日志文件等,通常初始化AnyChat SDK的代码如下(C++):

    // 打开(关闭)SDK的日志记录功能 
    02.BRAC_ActiveCallLog(TRUE); 
    03.      
    04.// 设置SDK核心组件所在目录 
    05.CHAR szCoreSDKPath[MAX_PATH] = {0}; 
    06.GetModuleFileName(NULL,szCoreSDKPath,sizeof(szCoreSDKPath)); 
    07.(strrchr(szCoreSDKPath,'\\'))[1] = 0;  
    08.BRAC_SetSDKOption(BRAC_SO_CORESDK_PATH,szCoreSDKPath,strlen(szCoreSDKPath)); 
    09.      
    10.// 根据BRAC_InitSDK的第二个参数:dwFuncMode,来告诉SDK该如何处理相关的任务(详情请参考开发文档) 
    11.DWORD dwFuncMode = BRAC_FUNC_VIDEO_CBDATA | BRAC_FUNC_AUDIO_AUTOPLAY | BRAC_FUNC_CHKDEPENDMODULE | BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_NET_SUPPORTUPNP | BRAC_FUNC_FIREWALL_OPEN | 
    12.BRAC_FUNC_AUDIO_AUTOVOLUME | BRAC_FUNC_CONFIG_LOCALINI; 
    13.BRAC_InitSDK(this->GetSafeHwnd()/*NULL*/,dwFuncMode); 
    14.      
    15.// 设置录像临时文件保存路径 
    16.CHAR szRecordDirectory[MAX_PATH] = {0}; 
    17.::GetModuleFileName(NULL,szRecordDirectory,MAX_PATH); 
    18.(strrchr(szRecordDirectory,'\\'))[1] = 0;  
    19.strcat(szRecordDirectory,"Record"); 
    20.BRAC_SetSDKOption(BRAC_SO_RECORD_TMPDIR,szRecordDirectory,strlen(szRecordDirectory)); 
    21.  
    22.// 设置录像文件质量参数 
    23.DWORD dwVideoBitrate = 200 * 1000;  // 200kbps 
    24.BRAC_SetSDKOption(BRAC_SO_RECORD_VIDEOBR,(PCHAR)&dwVideoBitrate,sizeof(DWORD)); 
    25.DWORD dwAudioBitrate = 96 * 1000;   // 96kbps 
    26.BRAC_SetSDKOption(BRAC_SO_RECORD_AUDIOBR,(PCHAR)&dwAudioBitrate,sizeof(DWORD)); 
    27.      
    28.// 设置快照临时文件保存路径 
    29.CHAR szSnapShotDirectory[MAX_PATH] = {0}; 
    30.::GetModuleFileName(NULL,szSnapShotDirectory,MAX_PATH); 
    31.(strrchr(szSnapShotDirectory,'\\'))[1] = 0;  
    32.strcat(szSnapShotDirectory,"SnapShot"); 
    33.BRAC_SetSDKOption(BRAC_SO_SNAPSHOT_TMPDIR,szSnapShotDirectory,strlen(szSnapShotDirectory)); 
    34.      
    35.// 设置SDK临时文件路径 
    36.CHAR szTempPath[MAX_PATH] = {0}; 
    37.::GetModuleFileName(NULL,szTempPath,MAX_PATH); 
    38.(strrchr(szTempPath,'\\'))[1] = 0;  
    39.strcat(szTempPath,"Temp"); 
    40.BRAC_SetSDKOption(BRAC_SO_CORESDK_TMPDIR,szTempPath,strlen(szTempPath)); 
    41.  
    42.// 启用音频自动参数功能(默认关闭) 
    43.DWORD bAudioAutoParam = TRUE; 
    44.BRAC_SetSDKOption(BRAC_SO_AUDIO_AUTOPARAM,(PCHAR)&bAudioAutoParam,sizeof(DWORD));
    

    二、登录系统

    当第一步初始化完成之后,便可以连接服务器、验证用户身份。通常调用代码如下(C++):

    // 连接服务器 
    2.BRAC_Connect("211.155.25.90",8906); 
    3.// 登录系统 
    4.BRAC_Login("testuser","",0);
    

    连接服务器与登录系统都是一个异步的过程,调用后会立即返回,其中:

    a、连接服务器成功,或是失败,将会触发异步消息:115. 网络连接消息

    b、登录系统成功,或是失败,将会触发异步消息:116. 登录系统消息

    所以应用程序需要响应这些异步消息(或处理:145. 异步消息通知回调函数)才能知道连接服务器、登录系统是否成功。

    登录系统成功后,如果需要实现即时通讯应用中的好友列表(AnyChat默认没有实现),则需要利用AnyChat的扩展API接口与Server SDK来配合实现,具体实现方案可参考SDK包中的:doc\server\目录下的《AnyChat Server SDK 开发指南》第6章节。

    登录系统成功后,服务器会返回一个32位的用户ID,如果登录时没有传入密码参数,则系统会认为是游客登录,并分配一个独立的用户ID(如-1、-2等),如果登录时传入了密码参数,则登录请求将会交给“SDK Filter Plus”接口,或“Server SDK”对应的接口,用户可开发一个自己的服务器插件“SDK Filter Plus”,或是调用“Server SDK”所对应的API来处理用户身份验证的请求,完成对用户ID的管理,实现与第三方系统的互联互通,详细内容可参考SDK包中的:doc\server\目录下的相关文档。

    三、进入房间

    在第二步登录系统成功之后,就可以进入房间,因为只有在房间中,才能完成语音和视频的交互。通常调用代码如下(C++):

    // 进入房间 
    2.BRAC_EnterRoom(1,"",0);
    

    房间由服务器动态管理,由32位的房间ID号来唯一标示,当客户端指定的房间ID号不存在时,服务器将会自动创建。进入房间也是一个异步的过程,是否成功将会触发异步消息:117. 自己进入房间消息,进入房间成功后,服务器会把当前房间的在线用户列表传给客户端,传输完成后,将会触发异步消息:121. 当前房间在线用户消息(该消息只触发一次),只有收到服务器的在线用户列表后,才能对房间内的用户进行音视频的相关操作。

    当自己进入房间成功,且收到服务器的在线用户消息后,有新的用户进入房间,或是老用户离开房间,将会触发异步消息:119. 用户进入(离开)房间消息,这样自己便知道谁进入,或是离开了房间。

    1、打开自己的音视频

    进入房间成功之后,便可以打开自己的音视频设备,通常调用代码如下(C++):

    // 打开自己的视频设备 
    2.BRAC_UserCameraControl(-1,TRUE); 
    3.// 打开自己的音频设备 
    4.BRAC_UserSpeakControl(-1,TRUE);
    

    打开自己的设备后,并不会立即上传音视频流,只有当其它用户请求自己的音视频数据时(可单独请求音频流,或视频流)才对外传输,参考:174. AnyChat在打开音频设备的同时会自动发布视频数据吗?,打开自己的音视频设备,默认是按服务器的配置信息来初始化设备(如采样分辨率、视频帧率、音频的采样频率等),如需要在客户端程序中调节音、视频质量,参考:187. 如何修改音频通信质量?、175. 如何设置AnyChat视频质量?

    2、请求其它用户的音视频

    如果需要显示其它用户的音视频,则必须在收到房间用户列表消息后,请求对方的音视频流,然后对方才将音视频流传输过来,通常请求其它用户的音视频数据调用代码如下(C++):

    // 请求对方的视频流 
    2.BRAC_UserCameraControl(dwUserId,TRUE); 
    3.// 请求对方的音频流 
    4.BRAC_UserSpeakControl(dwUserId,TRUE);
    

    数据传输优先P2P方式,只有当P2P不通时,才由服务器转发,P2P的NAT打洞过程,以及数据流传输策略均由服务器控制,只要有请求,而且对方已打开了自己的音视频设备,则就能收到对方的音视频流数据。

    3、音视频的播放与显示

    当收到其它用户的音频数据后:

    a)如果在初始化时设置了“BRAC_FUNC_AUDIO_AUTOPLAY”标志,则SDK内部将会自动播放,自动混音;

    b)如果在初始化时设置了“BRAC_FUNC_AUDIO_CBDATA”标志,则SDK会将解码后的音频数据(PCM格式)通过回调函数回调给上层应用。

    当收到其它用户的视频数据后

    a)如果在初始化时设置了“BRAC_FUNC_VIDEO_AUTODISP”标志,并且调用了API:31. BRAC_SetVideoPos,则SDK内部将会把视频显示到指定的窗体的指定位置(在指定位置上自动迭加一个视频窗口);

    b)如果在初始化时设置了“BRAC_FUNC_VIDEO_CBDATA”标志,则SDK会将解码后的视频数据(RGB、YUV)通过回调函数回调给上层应用,由上层应用自己来绘制,或渲染,该模式适合于DirectX、HGE等没有窗口模式下的应用程序,或是上层应用需要对视频进行特殊处理的场合,如迭加文字、logo等。

    4、文字交互

    成功进入房间后, 便可以调用API接口向指定用户,或是房间中的所有用户发送文字消息:

    // 发送文字消息 
    2.CString strInput = "hello world"; 
    3.BRAC_SendTextMessage(-1,FALSE,strInput.GetBuffer(0),strInput.GetLength());
    

    其它用户收到自己发送的文字消息后,便会触发回调函数:132. 文字消息回调函数,通过处理回调消息,然后将收到的文字消息显示在界面上,便可实现文字的交互。

    5、业务逻辑处理

    AnyChat SDK内置的基本逻辑是:当自己的音视频设备打开后,别的用户有请求,便会将流媒体数据传输给对方,而没有任何何业务逻辑。

    a)如要实现视频会议系统,则用户进入房间后,就需要知道谁是主持人,然后打开主持人的视频;

    b)如要实现视频聊天系统,则用户进入房间后,就需要知道当前房间有几个公麦,谁在公麦上,然后打开对应公麦用户的视频等;

    c)……

    这些业务逻辑需要与服务器端的“SDK Filter Plus”或“AnyChat Server SDK”互相配合来实现,具体的实现方案可参考SDK包中的:doc\server\目录下的《AnyChat Server SDK 开发指南》第6章节。

    四、释放资源

    与前面连接服务器、登录系统、进入房间对应的,退出系统的过程是:离开房间、注销系统、释放资源,通常调用代码如下(C++):

    // 离开房间 
    2.BRAC_LeaveRoom(-1); 
    3.// 注销系统(将关闭网络连接) 
    4.BRAC_Logout(); 
    5.// 释放资源 
    6.BRAC_Release();
    

    离开房间后,可以进入新的房间,系统注销之后,可以再次调用连接服务器的API接口,但是释放资源后,SDK将不再工作。

  • 相关阅读:
    洛谷 P1233 木棍加工
    洛谷 P3378 【模板】堆(小根堆)
    leetcode难度及面试频率
    设计模式大全
    多线程经典面试题
    查找子字符串----KMP算法深入剖析
    线程与进程的区别
    海量数据面试题----分而治之/hash映射 + hash统计 + 堆/快速/归并排序
    解析STL中典型的内存分配
    C++ 常量类型 const 详解
  • 原文地址:https://www.cnblogs.com/ilscott/p/2997966.html
Copyright © 2011-2022 走看看