- 浏览: 56284 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
c_24363:
你好。为什么我把你的代码弄到我的项目里,当用户进入房间后,然后 ...
200行Java代码实现Android下的视频通话 -
zhuyz89:
有空试试
200行Java代码实现Android下的视频通话
BRAnyChatSDKDemoDlg.cpp : implementation file
//
#include "stdafx.h"
#include <WINSOCK2.H>
#include "BRAnyChatSDKDemo.h"
#include "BRAnyChatSDKDemoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define REFRESH_TRANSTASK_STATUS_TIMER 1 ///< 刷新传输任务状态定时器
#define REFRESH_SPEAKVOLUME_TIMER 2 ///< 更新用户说话音量定时器
#define REFRESH_RECORDSTATE_TIMER 3 ///< 更新录像状态定时器
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBRAnyChatSDKDemoDlg dialog
CBRAnyChatSDKDemoDlg::CBRAnyChatSDKDemoDlg(CWnd* pParent )
: CDialog(CBRAnyChatSDKDemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CBRAnyChatSDKDemoDlg)
m_bEnableAGC = TRUE;
m_bEnableEcho = TRUE;
m_bEnableNS = TRUE;
m_bEnableVAD = TRUE;
m_iPort = 8906;
m_iRoomId = 1;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CBRAnyChatSDKDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBRAnyChatSDKDemoDlg)
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME0, m_ctrlSpeakVolume0);
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME1, m_ctrlSpeakVolume1);
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME2, m_ctrlSpeakVolume2);
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME3, m_ctrlSpeakVolume3);
DDX_Control(pDX, IDC_SLIDER_OUTVOLUME, m_ctrlOutVolume);
DDX_Control(pDX, IDC_SLIDER_INVOLUME, m_ctrlInVolume);
DDX_Control(pDX, IDC_COMBO_VCAPTURE, m_cbVideoCapture);
DDX_Control(pDX, IDC_COMBO_ACAPTURE, m_cbAudioCapture);
DDX_Control(pDX, IDC_EDIT_LOG, m_ctrlEditLog);
DDX_Check(pDX, IDC_CHECK_AGC, m_bEnableAGC);
DDX_Check(pDX, IDC_CHECK_ECHO, m_bEnableEcho);
DDX_Check(pDX, IDC_CHECK_NS, m_bEnableNS);
DDX_Check(pDX, IDC_CHECK_VAD, m_bEnableVAD);
DDX_Text(pDX, IDC_EDIT_PORT, m_iPort);
DDX_Text(pDX, IDC_EDIT_ROOMID, m_iRoomId);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CBRAnyChatSDKDemoDlg, CDialog)
//{{AFX_MSG_MAP(CBRAnyChatSDKDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_BUTTON_INIT, OnButtonInit)
ON_MESSAGE(WM_GV_CONNECT,OnGVClientConnect)
ON_MESSAGE(WM_GV_LOGINSYSTEM,OnGVClientLogin)
ON_MESSAGE(WM_GV_ENTERROOM,OnGVClientEnterRoom)
ON_MESSAGE(WM_GV_ONLINEUSER,OnGVClientOnlineUser)
ON_MESSAGE(WM_GV_USERATROOM,OnGVClientUserAtRoom)
ON_MESSAGE(WM_GV_MICSTATECHANGE,OnGVClientMicStateChange)
ON_MESSAGE(WM_GV_LINKCLOSE,OnGVClientLinkClose)
ON_MESSAGE(WM_GV_CHATMODECHG,OnGVClientChatModeChange)
ON_BN_CLICKED(IDC_BUTTON_ENTERROOM, OnButtonEnterRoom)
ON_BN_CLICKED(IDC_BUTTON_LEAVEROOM, OnButtonLeaveRoom)
ON_BN_CLICKED(IDC_BUTTON_VIDEOPROPERTY, OnButtonVideoproperty)
ON_BN_CLICKED(IDC_BUTTON_REFRESHCAPTURE, OnButtonRefreshCapture)
ON_CBN_SELCHANGE(IDC_COMBO_VCAPTURE, OnSelchangeComboVideoCapture)
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_OUTVOLUME, OnSliderOutVolumeChange)
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_INVOLUME, OnOnSliderInVolumeChange)
ON_CBN_SELCHANGE(IDC_COMBO_ACAPTURE, OnSelChangeComboAudioCapture)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_SENDFILE, OnButtonSendFile)
ON_BN_CLICKED(IDC_CHECK_VAD, OnCheckVad)
ON_BN_CLICKED(IDC_CHECK_AGC, OnCheckAgc)
ON_BN_CLICKED(IDC_CHECK_ECHO, OnCheckEcho)
ON_BN_CLICKED(IDC_CHECK_NS, OnCheckNs)
ON_BN_CLICKED(IDC_BUTTON_TRANSBUF, OnButtonTransbuf)
ON_BN_CLICKED(IDC_BUTTON_RELEASE, OnButtonRelease)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL0, OnButtonVideoctrl0)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL1, OnButtonVideoctrl1)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL2, OnButtonVideoctrl2)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL3, OnButtonVideoctrl3)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL0, OnButtonAudioctrl0)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL1, OnButtonAudioctrl1)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL2, OnButtonAudioctrl2)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL3, OnButtonAudioctrl3)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL0, OnButtonRecordctrl0)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL1, OnButtonRecordctrl1)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL2, OnButtonRecordctrl2)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL3, OnButtonRecordctrl3)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL0, OnButtonSnapshotctrl0)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL1, OnButtonSnapshotctrl1)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL2, OnButtonSnapshotctrl2)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL3, OnButtonSnapshotctrl3)
ON_BN_CLICKED(IDC_BUTTON_LOGIN, OnButtonLogin)
ON_BN_CLICKED(IDC_BUTTON_LOGOUT, OnButtonLogout)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CALLBACK VideoData_CallBack(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, BITMAPINFOHEADER bmiHeader, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
pDemoDlg->DrawUserVideo(dwUserid,lpBuf,dwLen,bmiHeader);
}
void CALLBACK AudioData_CallBack(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, WAVEFORMATEX waveFormatEx, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
// do something ...
}
}
void CALLBACK VolumeChange_CallBack(BRAC_AudioDevice device, DWORD dwCurrentVolume, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
if(device == BRAC_AD_WAVEIN)
pDemoDlg->OnWaveInVolumeChange(dwCurrentVolume);
else
pDemoDlg->OnWaveOutVolumeChange(dwCurrentVolume);
}
}
// 透明通道数据回调函数定义
void CALLBACK TransBuffer_CallBack(DWORD dwUserid, LPBYTE lpBuf, DWORD dwLen, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("TransBuffer_CallBack:dwUserid-%d, bufSize-%d",dwUserid,dwLen);
pDemoDlg->AppendLogString(strNotify);
}
}
// 透明通道数据扩展回调函数定义
void CALLBACK TransBufferEx_CallBack(DWORD dwUserid, LPBYTE lpBuf, DWORD dwLen, DWORD wParam, DWORD lParam, DWORD dwTaskId, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
BOOL bSuccess = FALSE;
if(dwLen > 1000)
{
bSuccess = lpBuf[1000] == 'Y' ? TRUE : FALSE;
}
CString strNotify;
strNotify.Format("TransBufferEx_CallBack:dwUserid-%d, bufSize-%d,verify:%s",dwUserid,dwLen,bSuccess ? "Success" : "Fail");
pDemoDlg->AppendLogString(strNotify);
}
}
// 文件传输回调函数定义
void CALLBACK TransFile_CallBack(DWORD dwUserid, LPCTSTR lpFileName, LPCTSTR lpTempFilePath, DWORD dwFileLength, DWORD wParam, DWORD lParam, DWORD dwTaskId, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("TransFile_CallBack:dwUserid-%d, lpFileName-%s, lpTempFilePath-%s",dwUserid,lpFileName,lpTempFilePath);
pDemoDlg->AppendLogString(strNotify);
}
}
// 录像、快照任务完成回调函数定义
void CALLBACK RecordSnapShot_CallBack(DWORD dwUserid, LPCTSTR lpFileName, DWORD dwParam, BOOL bRecordType, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("%s CallBack:dwUserid-%d, FilePathName-%s",bRecordType?"Record":"SnapShot",(int)dwUserid,lpFileName);
pDemoDlg->AppendLogString(strNotify);
}
}
// SDK Filter 通信数据回调函数定义
void CALLBACK SDKFilterData_CallBack(LPBYTE lpBuf, DWORD dwLen, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("SDK Filter CallBack:%s",lpBuf);
pDemoDlg->AppendLogString(strNotify);
}
}
void CBRAnyChatSDKDemoDlg::DrawUserVideo(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, BITMAPINFOHEADER bmiHeader)
{
// 根据用户ID号找到合适的显示区域
DWORD dwSite = -1;
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == (INT)dwUserid)
{
dwSite = i;
break;
}
}
if(dwSite == -1)
return;
CRect dispRect = m_UserRect[dwSite];
//构建Bitmap
BITMAPINFOHEADER *lpbmi = (BITMAPINFOHEADER*)malloc(sizeof(BITMAPINFOHEADER)+dwLen);
ZeroMemory(lpbmi,sizeof(BITMAPINFOHEADER)+dwLen);
memcpy((LPBYTE)lpbmi,&bmiHeader,sizeof(bmiHeader));
memcpy(((LPBYTE)lpbmi+sizeof(BITMAPINFOHEADER)),lpBuf,dwLen);
HDC hdc = ::GetDC(m_hWnd);
HDC dcMem = ::CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateDIBitmap(hdc,lpbmi,CBM_INIT,(LPBYTE)lpbmi+sizeof(BITMAPINFOHEADER),(LPBITMAPINFO)lpbmi,DIB_RGB_COLORS);
//绘图
HBITMAP holdbm = (HBITMAP)SelectObject(dcMem,hBitmap);
::SetStretchBltMode(hdc,COLORONCOLOR);
::StretchBlt(hdc,dispRect.left,dispRect.top,dispRect.Width(),dispRect.Height(),dcMem,0,0,bmiHeader.biWidth,bmiHeader.biHeight,SRCCOPY);
SelectObject(dcMem,holdbm);
::DeleteDC(dcMem);
::DeleteObject(hBitmap);
::ReleaseDC(m_hWnd,hdc);
free(lpbmi);
lpbmi = NULL;
}
BOOL CBRAnyChatSDKDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// 初始化每个视频显示位置信息
GetDlgItem(IDC_STATIC_USER0)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER0)->GetClientRect(m_UserRect[0]);
GetDlgItem(IDC_STATIC_USER0)->ClientToScreen(m_UserRect[0]);
ScreenToClient(m_UserRect[0]);
GetDlgItem(IDC_STATIC_USER1)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER1)->GetClientRect(m_UserRect[1]);
GetDlgItem(IDC_STATIC_USER1)->ClientToScreen(m_UserRect[1]);
ScreenToClient(m_UserRect[1]);
GetDlgItem(IDC_STATIC_USER2)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER2)->GetClientRect(m_UserRect[2]);
GetDlgItem(IDC_STATIC_USER2)->ClientToScreen(m_UserRect[2]);
ScreenToClient(m_UserRect[2]);
GetDlgItem(IDC_STATIC_USER3)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER3)->GetClientRect(m_UserRect[3]);
GetDlgItem(IDC_STATIC_USER3)->ClientToScreen(m_UserRect[3]);
ScreenToClient(m_UserRect[3]);
// 隐藏录像状态标志
GetDlgItem(IDC_STATIC_RECORDSTATE0)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_RECORDSTATE1)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_RECORDSTATE2)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_RECORDSTATE3)->ShowWindow(SW_HIDE);
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
m_dwTransTaskId = -1;
m_iPort = 8906;
m_iRoomId = 1;
SetDlgItemText(IDC_IPADDRESS_SERVER,"211.155.25.90");
SetDlgItemText(IDC_EDIT_USERNAME,"AnyChat3");
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CBRAnyChatSDKDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CBRAnyChatSDKDemoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CBRAnyChatSDKDemoDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CBRAnyChatSDKDemoDlg::OnDestroy()
{
BRAC_Release();
CDialog::OnDestroy();
}
void CBRAnyChatSDKDemoDlg::OnButtonInit()
{
// 获取SDK的版本信息
DWORD dwMainVer,dwSubVer;
CHAR szCompileTime[100] = {0};
BRAC_GetSDKVersion(dwMainVer,dwSubVer,szCompileTime,sizeof(szCompileTime));
CString logstr;
logstr.Format("AnyChat Core SDK Version:%d.%d(%s)",dwMainVer,dwSubVer,szCompileTime);
AppendLogString(logstr);
// 打开(关闭)SDK的日志记录功能
BRAC_ActiveCallLog(TRUE);
// 设置SDK核心组件所在目录(注:demo程序只是设置为当前目录,项目中需要设置为实际路径)
CHAR szCoreSDKPath[MAX_PATH] = {0};
GetModuleFileName(NULL,szCoreSDKPath,sizeof(szCoreSDKPath));
(strrchr(szCoreSDKPath,'\\'))[1] = 0;
BRAC_SetSDKOption(BRAC_SO_CORESDK_PATH,szCoreSDKPath,strlen(szCoreSDKPath));
// 根据BRAC_InitSDK的第二个参数:dwFuncMode,来告诉SDK该如何处理相关的任务(详情请参考开发文档)
DWORD dwFuncMode = BRAC_FUNC_VIDEO_AUTODISP | BRAC_FUNC_AUDIO_AUTOPLAY | BRAC_FUNC_CHKDEPENDMODULE |
BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_NET_SUPPORTUPNP | BRAC_FUNC_FIREWALL_OPEN |
BRAC_FUNC_AUDIO_AUTOVOLUME| BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_CONFIG_LOCALINI;
BRAC_InitSDK(this->GetSafeHwnd(),dwFuncMode);
BRAC_SetVideoDataCallBack(BRAC_PIX_FMT_RGB24,VideoData_CallBack,this);
BRAC_SetAudioDataCallBack(AudioData_CallBack,this);
BRAC_SetVolumeChangeCallBack(VolumeChange_CallBack,this);
BRAC_SetTransBufferExCallBack(TransBufferEx_CallBack,this);
BRAC_SetTransBufferCallBack(TransBuffer_CallBack,this);
BRAC_SetTransFileCallBack(TransFile_CallBack,this);
BRAC_SetRecordSnapShotCallBack(RecordSnapShot_CallBack,this);
BRAC_SetSDKFilterDataCallBack(SDKFilterData_CallBack,this);
// BRAC_SelectVideoCapture("USB 视频设备"); // 设置指定的视频设备,则在后面打开时,就可以打开该设备,如果不调用该方法,则会打开默认的视频设备
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_AGCCTRL,(PCHAR)&m_bEnableAGC,sizeof(m_bEnableAGC));
BRAC_SetSDKOption(BRAC_SO_AUDIO_VADCTRL,(PCHAR)&m_bEnableVAD,sizeof(m_bEnableVAD));
BRAC_SetSDKOption(BRAC_SO_AUDIO_NSCTRL,(PCHAR)&m_bEnableNS,sizeof(m_bEnableNS));
BRAC_SetSDKOption(BRAC_SO_AUDIO_ECHOCTRL,(PCHAR)&m_bEnableEcho,sizeof(m_bEnableEcho));
// 设置录像临时文件保存路径
CHAR szRecordDirectory[MAX_PATH] = {0};
::GetModuleFileName(NULL,szRecordDirectory,MAX_PATH);
(strrchr(szRecordDirectory,'\\'))[1] = 0;
strcat(szRecordDirectory,"Record");
BRAC_SetSDKOption(BRAC_SO_RECORD_TMPDIR,szRecordDirectory,strlen(szRecordDirectory));
// 设置录像文件质量参数
DWORD dwVideoBitrate = 200 * 1000; // 200kbps
BRAC_SetSDKOption(BRAC_SO_RECORD_VIDEOBR,(PCHAR)&dwVideoBitrate,sizeof(DWORD));
DWORD dwAudioBitrate = 96 * 1000; // 96kbps
BRAC_SetSDKOption(BRAC_SO_RECORD_AUDIOBR,(PCHAR)&dwAudioBitrate,sizeof(DWORD));
// 设置快照临时文件保存路径
CHAR szSnapShotDirectory[MAX_PATH] = {0};
::GetModuleFileName(NULL,szSnapShotDirectory,MAX_PATH);
(strrchr(szSnapShotDirectory,'\\'))[1] = 0;
strcat(szSnapShotDirectory,"SnapShot");
BRAC_SetSDKOption(BRAC_SO_SNAPSHOT_TMPDIR,szSnapShotDirectory,strlen(szSnapShotDirectory));
// 设置SDK临时文件路径
CHAR szTempPath[MAX_PATH] = {0};
::GetModuleFileName(NULL,szTempPath,MAX_PATH);
(strrchr(szTempPath,'\\'))[1] = 0;
strcat(szTempPath,"Temp");
BRAC_SetSDKOption(BRAC_SO_CORESDK_TMPDIR,szTempPath,strlen(szTempPath));
// 设置服务器认证密码
BRAC_SetServerAuthPass("BaiRuiTech"); // 需要与服务器配置项“SDKAuthPass”相同(大小写敏感),SDK才能正常连接到服务器
DWORD dwVolume = 0;
BRAC_AudioGetVolume(BRAC_AD_WAVEOUT,dwVolume);
m_ctrlOutVolume.SetPos(dwVolume);
dwVolume = 0;
BRAC_AudioGetVolume(BRAC_AD_WAVEIN,dwVolume);
m_ctrlInVolume.SetPos(dwVolume);
SetTimer(REFRESH_SPEAKVOLUME_TIMER,100,NULL);
SetTimer(REFRESH_RECORDSTATE_TIMER,1000,NULL);
}
void CBRAnyChatSDKDemoDlg::OnButtonLogin()
{
UpdateData(TRUE);
CString strServerIp,strUserName,strPassword;
GetDlgItemText(IDC_IPADDRESS_SERVER,strServerIp);
GetDlgItemText(IDC_EDIT_USERNAME,strUserName);
GetDlgItemText(IDC_EDIT_LOGINPASS,strPassword);
if(strServerIp.IsEmpty() || m_iPort <= 0)
{
AfxMessageBox("Invalid server ip address or port!");
return;
}
if(strUserName.IsEmpty())
{
AfxMessageBox("Must input username for login system!");
return;
}
BRAC_Connect(strServerIp.GetBuffer(0),m_iPort);
BRAC_Login(strUserName.GetBuffer(0),strPassword.GetBuffer(0),0);
}
void CBRAnyChatSDKDemoDlg::OnButtonEnterRoom()
{
UpdateData(TRUE);
BRAC_EnterRoom(m_iRoomId,"",0);
}
void CBRAnyChatSDKDemoDlg::OnButtonLeaveRoom()
{
BRAC_LeaveRoom(1);
// 保留自己的userid,因为这儿只是leaveroom,并非logout
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonLogout()
{
BRAC_Logout();
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRelease()
{
BRAC_Release();
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
m_dwTransTaskId = -1;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientConnect(WPARAM wParam, LPARAM lParam)
{
BOOL bSuccess = (BOOL)wParam;
AppendLogString(bSuccess ? "连接服务器成功..." : "连接服务器失败...");
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientLogin(WPARAM wParam, LPARAM lParam)
{
CString logstr;
DWORD dwUserID = wParam;
if(lParam == 0)
{
CHAR username[30]={0};
BRAC_GetUserName(dwUserID,username,sizeof(username));
logstr.Format("登录服务器成功,自己的用户编号为:%d(%s)",wParam,username);
// 将用户的ID保存在第一个位置,否则在回调函数里面可能找不到绘制的位置
m_iUserID[0] = dwUserID;
}
else
logstr.Format("登录服务器失败,出错代码为: %d ",lParam);
AppendLogString(logstr);
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientEnterRoom(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT roomid = (INT)wParam;
if(lParam == 0)
{
logstr.Format("成功进入编号为:%d 的房间",roomid);
BRAC_SetVideoPos(-1,m_hWnd,m_UserRect[0].left,m_UserRect[0].top,m_UserRect[0].right,m_UserRect[0].bottom);
BRAC_UserCameraControl(-1,TRUE);
BRAC_UserSpeakControl(-1,TRUE);
}
else
logstr.Format("申请进入房间失败,出错代码为: %d ",lParam);
AppendLogString(logstr);
return 0;
}
void CBRAnyChatSDKDemoDlg::AppendLogString(CString logstr)
{
m_strLogInfo += (logstr + "\r\n");
m_ctrlEditLog.SetWindowText(m_strLogInfo);
m_ctrlEditLog.LineScroll(m_ctrlEditLog.GetLineCount());
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientOnlineUser(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT onlinenum = (INT)wParam;
logstr.Format("在编号为:%d 的房间共有 %d 位在线用户",lParam, onlinenum);
AppendLogString(logstr);
DWORD dwUserNum = 0;
BRAC_GetOnlineUser(NULL,dwUserNum); ///< 首先获取房间内在线人数
if(!dwUserNum)
return 0;
LPDWORD lpdwUserList = (LPDWORD)malloc(sizeof(DWORD)*dwUserNum);
BRAC_GetOnlineUser(lpdwUserList,dwUserNum); ///< 真正获取在线用户列表
for(INT i=0; i< (INT)dwUserNum; i++)
{
DWORD userid = lpdwUserList[i];
// 给用户找一个空的位置显示面板(第0号位置留给自己)
INT site = -1;
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == -1)
{
site = i;
break;
}
}
if(site != -1)
{
BRAC_SetVideoPos(userid,m_hWnd,m_UserRect[site].left,m_UserRect[site].top,m_UserRect[site].right,m_UserRect[site].bottom);
BRAC_UserCameraControl(userid,TRUE);
BRAC_UserSpeakControl(userid,TRUE);
DWORD dwState = 0;
BRAC_GetCameraState(userid,dwState);
logstr.Format("用户%d 的视频状态是: %d",userid,dwState);
AppendLogString(logstr);
m_iUserID[site] = userid;
}
else ///< 已经没有位置了,Demo演示限制
break;
}
free(lpdwUserList);
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientUserAtRoom(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT userid = (INT)wParam;
BOOL bEnter = (BOOL)lParam;
CHAR username[30]={0};
BRAC_GetUserName(userid,username,sizeof(username));
logstr.Format("编号为:%d 的用户(%s) %s 房间",userid,username, bEnter ? "进入" : "离开");
AppendLogString(logstr);
if(bEnter)
{
// 给用户找一个空的位置显示面板(第0号位置留给自己)
INT site = -1;
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == -1)
{
site = i;
break;
}
}
if(site != -1)
{
BRAC_SetVideoPos(userid,m_hWnd,m_UserRect[site].left,m_UserRect[site].top,m_UserRect[site].right,m_UserRect[site].bottom);
BRAC_UserCameraControl(userid,TRUE);
BRAC_UserSpeakControl(userid,TRUE);
m_iUserID[site] = userid;
}
}
else
{
//清除该用户占用位置的信息
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == userid)
{
m_iUserID[i] = -1;
break;
}
}
}
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientMicStateChange(WPARAM wParam, LPARAM lParam)
{
CString logstr;
logstr.Format("编号为:%d 的用户 %s 本地Mic设备",wParam, lParam ? "打开" : "关闭");
AppendLogString(logstr);
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientLinkClose(WPARAM wParam, LPARAM lParam)
{
AppendLogString("网络连接已关闭(断开)");
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientChatModeChange(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT userid = (INT)wParam;
INT chatmode = (INT)lParam;
if(m_iUserID[0] == userid)
{
logstr.Format("自己(%d )的聊天模式改变,当前聊天模式为:%s",userid, chatmode == 0 ? "公聊模式" : "私聊模式");
}
else
logstr.Format("编号为:%d 的用户聊天模式改变,当前聊天模式为:%s",userid, chatmode == 0 ? "公聊模式" : "私聊模式");
AppendLogString(logstr);
return 0;
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoproperty()
{
BRAC_ShowLVProperty(m_hWnd,"AnyChat 本地视频画质调节");
}
void CBRAnyChatSDKDemoDlg::OnButtonRefreshCapture()
{
// 刷新视频采集设备下拉列表
PCHAR DeviceName[10] = {0};
DWORD DeviceNum = 10;
BRAC_EnumVideoCapture(DeviceName,DeviceNum);
m_cbVideoCapture.ResetContent();
INT i=0;
for(i=0; i<(INT)DeviceNum; i++)
{
if(DeviceName[i])
{
m_cbVideoCapture.AddString(DeviceName[i]);
::GlobalFree((HGLOBAL)DeviceName[i]);
DeviceName[i] = NULL;
}
}
// 选择当前打开的视频采集设备
CHAR szVideoDeviceName[100] = {0};
BRAC_GetCurVideoCapture(szVideoDeviceName,sizeof(szVideoDeviceName));
m_cbVideoCapture.SelectString(-1,szVideoDeviceName);
// 刷新音频采集设备下拉列表
DeviceNum = 10;
BRAC_EnumAudioCapture(DeviceName,DeviceNum);
m_cbAudioCapture.ResetContent();
for(i=0; i<(INT)DeviceNum; i++)
{
if(DeviceName[i])
{
m_cbAudioCapture.AddString(DeviceName[i]);
::GlobalFree((HGLOBAL)DeviceName[i]);
DeviceName[i] = NULL;
}
}
// 选择当前打开的视频采集设备
CHAR szAudioDeviceName[100] = {0};
BRAC_GetCurAudioCapture(szAudioDeviceName,sizeof(szAudioDeviceName));
m_cbAudioCapture.SelectString(-1,szAudioDeviceName);
}
void CBRAnyChatSDKDemoDlg::OnSelchangeComboVideoCapture()
{
CString strCaptureName;
m_cbVideoCapture.GetLBText(m_cbVideoCapture.GetCurSel(),strCaptureName);
BRAC_SelectVideoCapture(strCaptureName);
}
void CBRAnyChatSDKDemoDlg::OnSelChangeComboAudioCapture()
{
CString strCaptureName;
m_cbAudioCapture.GetLBText(m_cbAudioCapture.GetCurSel(),strCaptureName);
BRAC_SelectAudioCapture(strCaptureName);
}
void CBRAnyChatSDKDemoDlg::OnSliderOutVolumeChange(NMHDR* pNMHDR, LRESULT* pResult)
{
DWORD dwVolume = m_ctrlOutVolume.GetPos();
BRAC_AudioSetVolume(BRAC_AD_WAVEOUT,dwVolume);
*pResult = 0;
}
void CBRAnyChatSDKDemoDlg::OnOnSliderInVolumeChange(NMHDR* pNMHDR, LRESULT* pResult)
{
DWORD dwVolume = m_ctrlInVolume.GetPos();
BRAC_AudioSetVolume(BRAC_AD_WAVEIN,dwVolume);
*pResult = 0;
}
// 录音的音量发生改变
void CBRAnyChatSDKDemoDlg::OnWaveInVolumeChange(DWORD dwVolume)
{
m_ctrlInVolume.SetPos(dwVolume);
}
// 放音的音量发生改变
void CBRAnyChatSDKDemoDlg::OnWaveOutVolumeChange(DWORD dwVolume)
{
m_ctrlOutVolume.SetPos(dwVolume);
}
void CBRAnyChatSDKDemoDlg::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case REFRESH_TRANSTASK_STATUS_TIMER: // 刷新缓冲区传输任务状态
{
if(m_dwTransTaskId == -1)
{
KillTimer(REFRESH_TRANSTASK_STATUS_TIMER);
break;
}
DWORD ret;
DWORD dwStatus = 0;
ret = BRAC_QueryTransTaskInfo(-1,m_dwTransTaskId,BRAC_TRANSTASK_STATUS,(PCHAR)&dwStatus,sizeof(DWORD));
if(ret != GV_ERR_SUCCESS)
{
KillTimer(REFRESH_TRANSTASK_STATUS_TIMER);
m_dwTransTaskId = -1;
SetDlgItemText(IDC_STATIC_FILESTATUS,"");
if(ret == GV_ERR_TRANSBUF_NOTASK)
AppendLogString("传输任务不存在,可能对方已离开房间!");
else
AppendLogString("查询任务信息失败!");
break;
}
DOUBLE dbProgress = 0.0;
BRAC_QueryTransTaskInfo(-1,m_dwTransTaskId,BRAC_TRANSTASK_PROGRESS,(PCHAR)&dbProgress,sizeof(DOUBLE));
DWORD dwBitrate = 0;
BRAC_QueryTransTaskInfo(-1,m_dwTransTaskId,BRAC_TRANSTASK_BITRATE,(PCHAR)&dwBitrate,sizeof(DWORD));
CString strStatus;
switch(dwStatus)
{
case 1: strStatus = "Ready"; break;
case 2: strStatus = "Process"; break;
case 3: strStatus = "Finish"; break;
case 4: strStatus = "Cancel"; break;
case 5: strStatus = "Reject"; break;
default: strStatus = "Unkonw"; break;
}
if(dwStatus == 3) // finish
{
KillTimer(REFRESH_TRANSTASK_STATUS_TIMER);
m_dwTransTaskId = -1;
AppendLogString("传输任务已完成!");
}
CString strBitrate;
if(dwBitrate >= 1000 * 1000)
strBitrate.Format("%.02f Mbps",(float)dwBitrate/1000/1000);
else if(dwBitrate >= 1000)
strBitrate.Format("%.02f Kbps",(float)dwBitrate/1000);
else
strBitrate.Format("%.02f bps",(float)dwBitrate);
CString strNotify;
strNotify.Format("%s-%.02f%%-%s",strStatus,dbProgress,strBitrate);
SetDlgItemText(IDC_STATIC_FILESTATUS,strNotify);
}
case REFRESH_SPEAKVOLUME_TIMER: // 刷新用户说话音量
{
DOUBLE fSpeakVolume = 0.0;
if(m_iUserID[0] != -1 && BRAC_QueryUserState(m_iUserID[0],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume0.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume0.SetPos(0);
fSpeakVolume = 0.0;
if(m_iUserID[1] != -1 && BRAC_QueryUserState(m_iUserID[1],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume1.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume1.SetPos(0);
fSpeakVolume = 0.0;
if(m_iUserID[2] != -1 && BRAC_QueryUserState(m_iUserID[2],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume2.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume2.SetPos(0);
fSpeakVolume = 0.0;
if(m_iUserID[3] != -1 && BRAC_QueryUserState(m_iUserID[3],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume3.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume3.SetPos(0);
}
break;
case REFRESH_RECORDSTATE_TIMER: // 刷新录像状态
{
DWORD dwRecordState = 0;
if(m_iUserID[0] != -1 && BRAC_QueryUserState(m_iUserID[0],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE0)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
dwRecordState = 0;
if(m_iUserID[1] != -1 && BRAC_QueryUserState(m_iUserID[1],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE1)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
dwRecordState = 0;
if(m_iUserID[2] != -1 && BRAC_QueryUserState(m_iUserID[2],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE2)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
dwRecordState = 0;
if(m_iUserID[3] != -1 && BRAC_QueryUserState(m_iUserID[3],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE3)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
}
break;
default:
break;
}
CDialog::OnTimer(nIDEvent);
}
void CBRAnyChatSDKDemoDlg::OnButtonSendFile()
{
if(m_dwTransTaskId != -1) // 演示程序为了简洁,同时只允许传一个任务,实际上SDK是可以多任务并发的
return;
static TCHAR BASED_CODE szFilter[] = _T("All Files (*.*)||*.*\0");
CFileDialog dlg(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, szFilter, this);
if (dlg.DoModal() == IDOK)
{
CString strFileName = dlg.GetPathName();
DWORD dwTaskId = 0;
DWORD wParam = 1; // 上层应用程序可自定义wParam、lParam的值,这两个参数的值将被回调给对方
DWORD lParam = 2;
DWORD dwFlags = 0; // 该标志设置为0,则SDK将自动根据网络状态选择合适的传输途径(TCP、UDP or P2P)
DWORD ret = BRAC_TransFile(m_iUserID[1],strFileName.GetBuffer(0),wParam,lParam,dwFlags,dwTaskId);
if(ret == GV_ERR_SUCCESS)
{
m_dwTransTaskId = dwTaskId;
SetTimer(REFRESH_TRANSTASK_STATUS_TIMER,100,NULL);
}
else
{
CString strError;
strError.Format("创建文件传输任务失败,出错代码:%d",ret);
AppendLogString(strError);
SetDlgItemText(IDC_STATIC_FILESTATUS,"");
}
}
}
// 传输超大缓冲区任务演示
void CBRAnyChatSDKDemoDlg::OnButtonTransbuf()
{
if(m_dwTransTaskId != -1) // 演示程序为了简洁,同时只允许传一个任务,实际上SDK是可以多任务并发的
return;
PCHAR lpBuf = (PCHAR)malloc(10*1024); // 为了演示,创建一个10KByte大小的缓冲区
DWORD dwLen = 10*1024;
if(!lpBuf)
return;
lpBuf[1000] = 'Y'; // 演示的需要,为了验证收到的数据是否正确,在缓冲区中间某个位置设置一个标志,对方接收后,可判断该标志是否为设定值
DWORD dwTaskId = 0;
DWORD wParam = 3; // 上层应用程序可自定义wParam、lParam的值,这两个参数的值将被回调给对方
DWORD lParam = 4;
DWORD dwFlags = 0; // 该标志设置为0,则SDK将自动根据网络状态选择合适的传输途径(TCP、UDP or P2P)
DWORD ret = BRAC_TransBufferEx(m_iUserID[1],(PBYTE)lpBuf,dwLen,wParam,lParam,dwFlags,dwTaskId);
if(ret == GV_ERR_SUCCESS)
{
m_dwTransTaskId = dwTaskId;
SetTimer(REFRESH_TRANSTASK_STATUS_TIMER,100,NULL);
}
else
{
CString strError;
strError.Format("创建缓冲区传输任务失败,出错代码:%d",ret);
AppendLogString(strError);
SetDlgItemText(IDC_STATIC_FILESTATUS,"");
}
// 缓冲区调用完成后, 可以立即释放掉
free(lpBuf);
// BRAC_TransBuffer(m_iUserID[1],(LPBYTE)"bairuitech",10);
}
void CBRAnyChatSDKDemoDlg::OnCheckVad()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_VADCTRL,(PCHAR)&m_bEnableVAD,sizeof(m_bEnableVAD));
}
void CBRAnyChatSDKDemoDlg::OnCheckAgc()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_AGCCTRL,(PCHAR)&m_bEnableAGC,sizeof(m_bEnableAGC));
}
void CBRAnyChatSDKDemoDlg::OnCheckEcho()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_ECHOCTRL,(PCHAR)&m_bEnableEcho,sizeof(m_bEnableEcho));
}
void CBRAnyChatSDKDemoDlg::OnCheckNs()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_NSCTRL,(PCHAR)&m_bEnableNS,sizeof(m_bEnableNS));
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl0()
{
// 为了演示程序简单,这儿采用静态变量保存上一次的状态,可能不准确,因为可能在别的地方有打开,或是关闭的操作,下同
// 特别是当前用户离开房间,别的用户再进来时,初始状态将不准确
static BOOL bLastState = TRUE;
if(m_iUserID[0] != -1)
{
BRAC_UserCameraControl(m_iUserID[0],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl1()
{
static BOOL bLastState = TRUE;
if(m_iUserID[1] != -1)
{
BRAC_UserCameraControl(m_iUserID[1],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl2()
{
static BOOL bLastState = TRUE;
if(m_iUserID[2] != -1)
{
BRAC_UserCameraControl(m_iUserID[2],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl3()
{
static BOOL bLastState = TRUE;
if(m_iUserID[3] != -1)
{
BRAC_UserCameraControl(m_iUserID[3],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl0()
{
static BOOL bLastState = TRUE;
if(m_iUserID[0] != -1)
{
BRAC_UserSpeakControl(m_iUserID[0],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl1()
{
static BOOL bLastState = TRUE;
if(m_iUserID[1] != -1)
{
BRAC_UserSpeakControl(m_iUserID[1],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl2()
{
static BOOL bLastState = TRUE;
if(m_iUserID[2] != -1)
{
BRAC_UserSpeakControl(m_iUserID[2],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl3()
{
static BOOL bLastState = TRUE;
if(m_iUserID[3] != -1)
{
BRAC_UserSpeakControl(m_iUserID[3],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl0()
{
static BOOL bLastState = FALSE;
if(m_iUserID[0] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[0],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl1()
{
static BOOL bLastState = FALSE;
if(m_iUserID[1] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[1],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl2()
{
static BOOL bLastState = FALSE;
if(m_iUserID[2] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[2],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl3()
{
static BOOL bLastState = FALSE;
if(m_iUserID[3] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[3],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl0()
{
if(m_iUserID[0] != -1)
{
BRAC_SnapShot(m_iUserID[0],0,0);
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl1()
{
if(m_iUserID[1] != -1)
{
BRAC_SnapShot(m_iUserID[1],0,0);
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl2()
{
if(m_iUserID[2] != -1)
{
BRAC_SnapShot(m_iUserID[2],0,0);
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl3()
{
if(m_iUserID[3] != -1)
{
BRAC_SnapShot(m_iUserID[3],0,0);
}
}
复制代码
文字信息交流
点对点语音、视频通话
多方语音、视频交互
文件传输
拍照、录像
自定义缓冲区传输
…………
P2P+服务器转发,UPnP支持
音视频同步,多路混音
回音消除、噪音抑制、自动增益
网络自适应,3G网络优化
动态缓冲区控制
视频防马赛克处理
发言模式、放歌模式、卡拉OK模式,单声道、立体声自动切换
//
#include "stdafx.h"
#include <WINSOCK2.H>
#include "BRAnyChatSDKDemo.h"
#include "BRAnyChatSDKDemoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define REFRESH_TRANSTASK_STATUS_TIMER 1 ///< 刷新传输任务状态定时器
#define REFRESH_SPEAKVOLUME_TIMER 2 ///< 更新用户说话音量定时器
#define REFRESH_RECORDSTATE_TIMER 3 ///< 更新录像状态定时器
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBRAnyChatSDKDemoDlg dialog
CBRAnyChatSDKDemoDlg::CBRAnyChatSDKDemoDlg(CWnd* pParent )
: CDialog(CBRAnyChatSDKDemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CBRAnyChatSDKDemoDlg)
m_bEnableAGC = TRUE;
m_bEnableEcho = TRUE;
m_bEnableNS = TRUE;
m_bEnableVAD = TRUE;
m_iPort = 8906;
m_iRoomId = 1;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CBRAnyChatSDKDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBRAnyChatSDKDemoDlg)
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME0, m_ctrlSpeakVolume0);
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME1, m_ctrlSpeakVolume1);
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME2, m_ctrlSpeakVolume2);
DDX_Control(pDX, IDC_PROGRESS_SPEAKVOLUME3, m_ctrlSpeakVolume3);
DDX_Control(pDX, IDC_SLIDER_OUTVOLUME, m_ctrlOutVolume);
DDX_Control(pDX, IDC_SLIDER_INVOLUME, m_ctrlInVolume);
DDX_Control(pDX, IDC_COMBO_VCAPTURE, m_cbVideoCapture);
DDX_Control(pDX, IDC_COMBO_ACAPTURE, m_cbAudioCapture);
DDX_Control(pDX, IDC_EDIT_LOG, m_ctrlEditLog);
DDX_Check(pDX, IDC_CHECK_AGC, m_bEnableAGC);
DDX_Check(pDX, IDC_CHECK_ECHO, m_bEnableEcho);
DDX_Check(pDX, IDC_CHECK_NS, m_bEnableNS);
DDX_Check(pDX, IDC_CHECK_VAD, m_bEnableVAD);
DDX_Text(pDX, IDC_EDIT_PORT, m_iPort);
DDX_Text(pDX, IDC_EDIT_ROOMID, m_iRoomId);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CBRAnyChatSDKDemoDlg, CDialog)
//{{AFX_MSG_MAP(CBRAnyChatSDKDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_BUTTON_INIT, OnButtonInit)
ON_MESSAGE(WM_GV_CONNECT,OnGVClientConnect)
ON_MESSAGE(WM_GV_LOGINSYSTEM,OnGVClientLogin)
ON_MESSAGE(WM_GV_ENTERROOM,OnGVClientEnterRoom)
ON_MESSAGE(WM_GV_ONLINEUSER,OnGVClientOnlineUser)
ON_MESSAGE(WM_GV_USERATROOM,OnGVClientUserAtRoom)
ON_MESSAGE(WM_GV_MICSTATECHANGE,OnGVClientMicStateChange)
ON_MESSAGE(WM_GV_LINKCLOSE,OnGVClientLinkClose)
ON_MESSAGE(WM_GV_CHATMODECHG,OnGVClientChatModeChange)
ON_BN_CLICKED(IDC_BUTTON_ENTERROOM, OnButtonEnterRoom)
ON_BN_CLICKED(IDC_BUTTON_LEAVEROOM, OnButtonLeaveRoom)
ON_BN_CLICKED(IDC_BUTTON_VIDEOPROPERTY, OnButtonVideoproperty)
ON_BN_CLICKED(IDC_BUTTON_REFRESHCAPTURE, OnButtonRefreshCapture)
ON_CBN_SELCHANGE(IDC_COMBO_VCAPTURE, OnSelchangeComboVideoCapture)
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_OUTVOLUME, OnSliderOutVolumeChange)
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_INVOLUME, OnOnSliderInVolumeChange)
ON_CBN_SELCHANGE(IDC_COMBO_ACAPTURE, OnSelChangeComboAudioCapture)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_SENDFILE, OnButtonSendFile)
ON_BN_CLICKED(IDC_CHECK_VAD, OnCheckVad)
ON_BN_CLICKED(IDC_CHECK_AGC, OnCheckAgc)
ON_BN_CLICKED(IDC_CHECK_ECHO, OnCheckEcho)
ON_BN_CLICKED(IDC_CHECK_NS, OnCheckNs)
ON_BN_CLICKED(IDC_BUTTON_TRANSBUF, OnButtonTransbuf)
ON_BN_CLICKED(IDC_BUTTON_RELEASE, OnButtonRelease)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL0, OnButtonVideoctrl0)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL1, OnButtonVideoctrl1)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL2, OnButtonVideoctrl2)
ON_BN_CLICKED(IDC_BUTTON_VIDEOCTRL3, OnButtonVideoctrl3)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL0, OnButtonAudioctrl0)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL1, OnButtonAudioctrl1)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL2, OnButtonAudioctrl2)
ON_BN_CLICKED(IDC_BUTTON_AUDIOCTRL3, OnButtonAudioctrl3)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL0, OnButtonRecordctrl0)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL1, OnButtonRecordctrl1)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL2, OnButtonRecordctrl2)
ON_BN_CLICKED(IDC_BUTTON_RECORDCTRL3, OnButtonRecordctrl3)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL0, OnButtonSnapshotctrl0)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL1, OnButtonSnapshotctrl1)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL2, OnButtonSnapshotctrl2)
ON_BN_CLICKED(IDC_BUTTON_SNAPSHOTCTRL3, OnButtonSnapshotctrl3)
ON_BN_CLICKED(IDC_BUTTON_LOGIN, OnButtonLogin)
ON_BN_CLICKED(IDC_BUTTON_LOGOUT, OnButtonLogout)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CALLBACK VideoData_CallBack(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, BITMAPINFOHEADER bmiHeader, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
pDemoDlg->DrawUserVideo(dwUserid,lpBuf,dwLen,bmiHeader);
}
void CALLBACK AudioData_CallBack(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, WAVEFORMATEX waveFormatEx, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
// do something ...
}
}
void CALLBACK VolumeChange_CallBack(BRAC_AudioDevice device, DWORD dwCurrentVolume, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
if(device == BRAC_AD_WAVEIN)
pDemoDlg->OnWaveInVolumeChange(dwCurrentVolume);
else
pDemoDlg->OnWaveOutVolumeChange(dwCurrentVolume);
}
}
// 透明通道数据回调函数定义
void CALLBACK TransBuffer_CallBack(DWORD dwUserid, LPBYTE lpBuf, DWORD dwLen, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("TransBuffer_CallBack:dwUserid-%d, bufSize-%d",dwUserid,dwLen);
pDemoDlg->AppendLogString(strNotify);
}
}
// 透明通道数据扩展回调函数定义
void CALLBACK TransBufferEx_CallBack(DWORD dwUserid, LPBYTE lpBuf, DWORD dwLen, DWORD wParam, DWORD lParam, DWORD dwTaskId, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
BOOL bSuccess = FALSE;
if(dwLen > 1000)
{
bSuccess = lpBuf[1000] == 'Y' ? TRUE : FALSE;
}
CString strNotify;
strNotify.Format("TransBufferEx_CallBack:dwUserid-%d, bufSize-%d,verify:%s",dwUserid,dwLen,bSuccess ? "Success" : "Fail");
pDemoDlg->AppendLogString(strNotify);
}
}
// 文件传输回调函数定义
void CALLBACK TransFile_CallBack(DWORD dwUserid, LPCTSTR lpFileName, LPCTSTR lpTempFilePath, DWORD dwFileLength, DWORD wParam, DWORD lParam, DWORD dwTaskId, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("TransFile_CallBack:dwUserid-%d, lpFileName-%s, lpTempFilePath-%s",dwUserid,lpFileName,lpTempFilePath);
pDemoDlg->AppendLogString(strNotify);
}
}
// 录像、快照任务完成回调函数定义
void CALLBACK RecordSnapShot_CallBack(DWORD dwUserid, LPCTSTR lpFileName, DWORD dwParam, BOOL bRecordType, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("%s CallBack:dwUserid-%d, FilePathName-%s",bRecordType?"Record":"SnapShot",(int)dwUserid,lpFileName);
pDemoDlg->AppendLogString(strNotify);
}
}
// SDK Filter 通信数据回调函数定义
void CALLBACK SDKFilterData_CallBack(LPBYTE lpBuf, DWORD dwLen, LPVOID lpUserValue)
{
CBRAnyChatSDKDemoDlg* pDemoDlg = (CBRAnyChatSDKDemoDlg*)lpUserValue;
if(pDemoDlg)
{
CString strNotify;
strNotify.Format("SDK Filter CallBack:%s",lpBuf);
pDemoDlg->AppendLogString(strNotify);
}
}
void CBRAnyChatSDKDemoDlg::DrawUserVideo(DWORD dwUserid, LPVOID lpBuf, DWORD dwLen, BITMAPINFOHEADER bmiHeader)
{
// 根据用户ID号找到合适的显示区域
DWORD dwSite = -1;
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == (INT)dwUserid)
{
dwSite = i;
break;
}
}
if(dwSite == -1)
return;
CRect dispRect = m_UserRect[dwSite];
//构建Bitmap
BITMAPINFOHEADER *lpbmi = (BITMAPINFOHEADER*)malloc(sizeof(BITMAPINFOHEADER)+dwLen);
ZeroMemory(lpbmi,sizeof(BITMAPINFOHEADER)+dwLen);
memcpy((LPBYTE)lpbmi,&bmiHeader,sizeof(bmiHeader));
memcpy(((LPBYTE)lpbmi+sizeof(BITMAPINFOHEADER)),lpBuf,dwLen);
HDC hdc = ::GetDC(m_hWnd);
HDC dcMem = ::CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateDIBitmap(hdc,lpbmi,CBM_INIT,(LPBYTE)lpbmi+sizeof(BITMAPINFOHEADER),(LPBITMAPINFO)lpbmi,DIB_RGB_COLORS);
//绘图
HBITMAP holdbm = (HBITMAP)SelectObject(dcMem,hBitmap);
::SetStretchBltMode(hdc,COLORONCOLOR);
::StretchBlt(hdc,dispRect.left,dispRect.top,dispRect.Width(),dispRect.Height(),dcMem,0,0,bmiHeader.biWidth,bmiHeader.biHeight,SRCCOPY);
SelectObject(dcMem,holdbm);
::DeleteDC(dcMem);
::DeleteObject(hBitmap);
::ReleaseDC(m_hWnd,hdc);
free(lpbmi);
lpbmi = NULL;
}
BOOL CBRAnyChatSDKDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// 初始化每个视频显示位置信息
GetDlgItem(IDC_STATIC_USER0)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER0)->GetClientRect(m_UserRect[0]);
GetDlgItem(IDC_STATIC_USER0)->ClientToScreen(m_UserRect[0]);
ScreenToClient(m_UserRect[0]);
GetDlgItem(IDC_STATIC_USER1)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER1)->GetClientRect(m_UserRect[1]);
GetDlgItem(IDC_STATIC_USER1)->ClientToScreen(m_UserRect[1]);
ScreenToClient(m_UserRect[1]);
GetDlgItem(IDC_STATIC_USER2)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER2)->GetClientRect(m_UserRect[2]);
GetDlgItem(IDC_STATIC_USER2)->ClientToScreen(m_UserRect[2]);
ScreenToClient(m_UserRect[2]);
GetDlgItem(IDC_STATIC_USER3)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_USER3)->GetClientRect(m_UserRect[3]);
GetDlgItem(IDC_STATIC_USER3)->ClientToScreen(m_UserRect[3]);
ScreenToClient(m_UserRect[3]);
// 隐藏录像状态标志
GetDlgItem(IDC_STATIC_RECORDSTATE0)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_RECORDSTATE1)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_RECORDSTATE2)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STATIC_RECORDSTATE3)->ShowWindow(SW_HIDE);
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
m_dwTransTaskId = -1;
m_iPort = 8906;
m_iRoomId = 1;
SetDlgItemText(IDC_IPADDRESS_SERVER,"211.155.25.90");
SetDlgItemText(IDC_EDIT_USERNAME,"AnyChat3");
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CBRAnyChatSDKDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CBRAnyChatSDKDemoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CBRAnyChatSDKDemoDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CBRAnyChatSDKDemoDlg::OnDestroy()
{
BRAC_Release();
CDialog::OnDestroy();
}
void CBRAnyChatSDKDemoDlg::OnButtonInit()
{
// 获取SDK的版本信息
DWORD dwMainVer,dwSubVer;
CHAR szCompileTime[100] = {0};
BRAC_GetSDKVersion(dwMainVer,dwSubVer,szCompileTime,sizeof(szCompileTime));
CString logstr;
logstr.Format("AnyChat Core SDK Version:%d.%d(%s)",dwMainVer,dwSubVer,szCompileTime);
AppendLogString(logstr);
// 打开(关闭)SDK的日志记录功能
BRAC_ActiveCallLog(TRUE);
// 设置SDK核心组件所在目录(注:demo程序只是设置为当前目录,项目中需要设置为实际路径)
CHAR szCoreSDKPath[MAX_PATH] = {0};
GetModuleFileName(NULL,szCoreSDKPath,sizeof(szCoreSDKPath));
(strrchr(szCoreSDKPath,'\\'))[1] = 0;
BRAC_SetSDKOption(BRAC_SO_CORESDK_PATH,szCoreSDKPath,strlen(szCoreSDKPath));
// 根据BRAC_InitSDK的第二个参数:dwFuncMode,来告诉SDK该如何处理相关的任务(详情请参考开发文档)
DWORD dwFuncMode = BRAC_FUNC_VIDEO_AUTODISP | BRAC_FUNC_AUDIO_AUTOPLAY | BRAC_FUNC_CHKDEPENDMODULE |
BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_NET_SUPPORTUPNP | BRAC_FUNC_FIREWALL_OPEN |
BRAC_FUNC_AUDIO_AUTOVOLUME| BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_CONFIG_LOCALINI;
BRAC_InitSDK(this->GetSafeHwnd(),dwFuncMode);
BRAC_SetVideoDataCallBack(BRAC_PIX_FMT_RGB24,VideoData_CallBack,this);
BRAC_SetAudioDataCallBack(AudioData_CallBack,this);
BRAC_SetVolumeChangeCallBack(VolumeChange_CallBack,this);
BRAC_SetTransBufferExCallBack(TransBufferEx_CallBack,this);
BRAC_SetTransBufferCallBack(TransBuffer_CallBack,this);
BRAC_SetTransFileCallBack(TransFile_CallBack,this);
BRAC_SetRecordSnapShotCallBack(RecordSnapShot_CallBack,this);
BRAC_SetSDKFilterDataCallBack(SDKFilterData_CallBack,this);
// BRAC_SelectVideoCapture("USB 视频设备"); // 设置指定的视频设备,则在后面打开时,就可以打开该设备,如果不调用该方法,则会打开默认的视频设备
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_AGCCTRL,(PCHAR)&m_bEnableAGC,sizeof(m_bEnableAGC));
BRAC_SetSDKOption(BRAC_SO_AUDIO_VADCTRL,(PCHAR)&m_bEnableVAD,sizeof(m_bEnableVAD));
BRAC_SetSDKOption(BRAC_SO_AUDIO_NSCTRL,(PCHAR)&m_bEnableNS,sizeof(m_bEnableNS));
BRAC_SetSDKOption(BRAC_SO_AUDIO_ECHOCTRL,(PCHAR)&m_bEnableEcho,sizeof(m_bEnableEcho));
// 设置录像临时文件保存路径
CHAR szRecordDirectory[MAX_PATH] = {0};
::GetModuleFileName(NULL,szRecordDirectory,MAX_PATH);
(strrchr(szRecordDirectory,'\\'))[1] = 0;
strcat(szRecordDirectory,"Record");
BRAC_SetSDKOption(BRAC_SO_RECORD_TMPDIR,szRecordDirectory,strlen(szRecordDirectory));
// 设置录像文件质量参数
DWORD dwVideoBitrate = 200 * 1000; // 200kbps
BRAC_SetSDKOption(BRAC_SO_RECORD_VIDEOBR,(PCHAR)&dwVideoBitrate,sizeof(DWORD));
DWORD dwAudioBitrate = 96 * 1000; // 96kbps
BRAC_SetSDKOption(BRAC_SO_RECORD_AUDIOBR,(PCHAR)&dwAudioBitrate,sizeof(DWORD));
// 设置快照临时文件保存路径
CHAR szSnapShotDirectory[MAX_PATH] = {0};
::GetModuleFileName(NULL,szSnapShotDirectory,MAX_PATH);
(strrchr(szSnapShotDirectory,'\\'))[1] = 0;
strcat(szSnapShotDirectory,"SnapShot");
BRAC_SetSDKOption(BRAC_SO_SNAPSHOT_TMPDIR,szSnapShotDirectory,strlen(szSnapShotDirectory));
// 设置SDK临时文件路径
CHAR szTempPath[MAX_PATH] = {0};
::GetModuleFileName(NULL,szTempPath,MAX_PATH);
(strrchr(szTempPath,'\\'))[1] = 0;
strcat(szTempPath,"Temp");
BRAC_SetSDKOption(BRAC_SO_CORESDK_TMPDIR,szTempPath,strlen(szTempPath));
// 设置服务器认证密码
BRAC_SetServerAuthPass("BaiRuiTech"); // 需要与服务器配置项“SDKAuthPass”相同(大小写敏感),SDK才能正常连接到服务器
DWORD dwVolume = 0;
BRAC_AudioGetVolume(BRAC_AD_WAVEOUT,dwVolume);
m_ctrlOutVolume.SetPos(dwVolume);
dwVolume = 0;
BRAC_AudioGetVolume(BRAC_AD_WAVEIN,dwVolume);
m_ctrlInVolume.SetPos(dwVolume);
SetTimer(REFRESH_SPEAKVOLUME_TIMER,100,NULL);
SetTimer(REFRESH_RECORDSTATE_TIMER,1000,NULL);
}
void CBRAnyChatSDKDemoDlg::OnButtonLogin()
{
UpdateData(TRUE);
CString strServerIp,strUserName,strPassword;
GetDlgItemText(IDC_IPADDRESS_SERVER,strServerIp);
GetDlgItemText(IDC_EDIT_USERNAME,strUserName);
GetDlgItemText(IDC_EDIT_LOGINPASS,strPassword);
if(strServerIp.IsEmpty() || m_iPort <= 0)
{
AfxMessageBox("Invalid server ip address or port!");
return;
}
if(strUserName.IsEmpty())
{
AfxMessageBox("Must input username for login system!");
return;
}
BRAC_Connect(strServerIp.GetBuffer(0),m_iPort);
BRAC_Login(strUserName.GetBuffer(0),strPassword.GetBuffer(0),0);
}
void CBRAnyChatSDKDemoDlg::OnButtonEnterRoom()
{
UpdateData(TRUE);
BRAC_EnterRoom(m_iRoomId,"",0);
}
void CBRAnyChatSDKDemoDlg::OnButtonLeaveRoom()
{
BRAC_LeaveRoom(1);
// 保留自己的userid,因为这儿只是leaveroom,并非logout
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonLogout()
{
BRAC_Logout();
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRelease()
{
BRAC_Release();
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
m_dwTransTaskId = -1;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientConnect(WPARAM wParam, LPARAM lParam)
{
BOOL bSuccess = (BOOL)wParam;
AppendLogString(bSuccess ? "连接服务器成功..." : "连接服务器失败...");
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientLogin(WPARAM wParam, LPARAM lParam)
{
CString logstr;
DWORD dwUserID = wParam;
if(lParam == 0)
{
CHAR username[30]={0};
BRAC_GetUserName(dwUserID,username,sizeof(username));
logstr.Format("登录服务器成功,自己的用户编号为:%d(%s)",wParam,username);
// 将用户的ID保存在第一个位置,否则在回调函数里面可能找不到绘制的位置
m_iUserID[0] = dwUserID;
}
else
logstr.Format("登录服务器失败,出错代码为: %d ",lParam);
AppendLogString(logstr);
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientEnterRoom(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT roomid = (INT)wParam;
if(lParam == 0)
{
logstr.Format("成功进入编号为:%d 的房间",roomid);
BRAC_SetVideoPos(-1,m_hWnd,m_UserRect[0].left,m_UserRect[0].top,m_UserRect[0].right,m_UserRect[0].bottom);
BRAC_UserCameraControl(-1,TRUE);
BRAC_UserSpeakControl(-1,TRUE);
}
else
logstr.Format("申请进入房间失败,出错代码为: %d ",lParam);
AppendLogString(logstr);
return 0;
}
void CBRAnyChatSDKDemoDlg::AppendLogString(CString logstr)
{
m_strLogInfo += (logstr + "\r\n");
m_ctrlEditLog.SetWindowText(m_strLogInfo);
m_ctrlEditLog.LineScroll(m_ctrlEditLog.GetLineCount());
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientOnlineUser(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT onlinenum = (INT)wParam;
logstr.Format("在编号为:%d 的房间共有 %d 位在线用户",lParam, onlinenum);
AppendLogString(logstr);
DWORD dwUserNum = 0;
BRAC_GetOnlineUser(NULL,dwUserNum); ///< 首先获取房间内在线人数
if(!dwUserNum)
return 0;
LPDWORD lpdwUserList = (LPDWORD)malloc(sizeof(DWORD)*dwUserNum);
BRAC_GetOnlineUser(lpdwUserList,dwUserNum); ///< 真正获取在线用户列表
for(INT i=0; i< (INT)dwUserNum; i++)
{
DWORD userid = lpdwUserList[i];
// 给用户找一个空的位置显示面板(第0号位置留给自己)
INT site = -1;
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == -1)
{
site = i;
break;
}
}
if(site != -1)
{
BRAC_SetVideoPos(userid,m_hWnd,m_UserRect[site].left,m_UserRect[site].top,m_UserRect[site].right,m_UserRect[site].bottom);
BRAC_UserCameraControl(userid,TRUE);
BRAC_UserSpeakControl(userid,TRUE);
DWORD dwState = 0;
BRAC_GetCameraState(userid,dwState);
logstr.Format("用户%d 的视频状态是: %d",userid,dwState);
AppendLogString(logstr);
m_iUserID[site] = userid;
}
else ///< 已经没有位置了,Demo演示限制
break;
}
free(lpdwUserList);
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientUserAtRoom(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT userid = (INT)wParam;
BOOL bEnter = (BOOL)lParam;
CHAR username[30]={0};
BRAC_GetUserName(userid,username,sizeof(username));
logstr.Format("编号为:%d 的用户(%s) %s 房间",userid,username, bEnter ? "进入" : "离开");
AppendLogString(logstr);
if(bEnter)
{
// 给用户找一个空的位置显示面板(第0号位置留给自己)
INT site = -1;
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == -1)
{
site = i;
break;
}
}
if(site != -1)
{
BRAC_SetVideoPos(userid,m_hWnd,m_UserRect[site].left,m_UserRect[site].top,m_UserRect[site].right,m_UserRect[site].bottom);
BRAC_UserCameraControl(userid,TRUE);
BRAC_UserSpeakControl(userid,TRUE);
m_iUserID[site] = userid;
}
}
else
{
//清除该用户占用位置的信息
for(INT i=1; i<DEMO_SHOW_USER_NUM; i++)
{
if(m_iUserID[i] == userid)
{
m_iUserID[i] = -1;
break;
}
}
}
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientMicStateChange(WPARAM wParam, LPARAM lParam)
{
CString logstr;
logstr.Format("编号为:%d 的用户 %s 本地Mic设备",wParam, lParam ? "打开" : "关闭");
AppendLogString(logstr);
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientLinkClose(WPARAM wParam, LPARAM lParam)
{
AppendLogString("网络连接已关闭(断开)");
for(INT i=0; i<DEMO_SHOW_USER_NUM; i++)
{
m_iUserID[i] = -1;
}
return 0;
}
LRESULT CBRAnyChatSDKDemoDlg::OnGVClientChatModeChange(WPARAM wParam, LPARAM lParam)
{
CString logstr;
INT userid = (INT)wParam;
INT chatmode = (INT)lParam;
if(m_iUserID[0] == userid)
{
logstr.Format("自己(%d )的聊天模式改变,当前聊天模式为:%s",userid, chatmode == 0 ? "公聊模式" : "私聊模式");
}
else
logstr.Format("编号为:%d 的用户聊天模式改变,当前聊天模式为:%s",userid, chatmode == 0 ? "公聊模式" : "私聊模式");
AppendLogString(logstr);
return 0;
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoproperty()
{
BRAC_ShowLVProperty(m_hWnd,"AnyChat 本地视频画质调节");
}
void CBRAnyChatSDKDemoDlg::OnButtonRefreshCapture()
{
// 刷新视频采集设备下拉列表
PCHAR DeviceName[10] = {0};
DWORD DeviceNum = 10;
BRAC_EnumVideoCapture(DeviceName,DeviceNum);
m_cbVideoCapture.ResetContent();
INT i=0;
for(i=0; i<(INT)DeviceNum; i++)
{
if(DeviceName[i])
{
m_cbVideoCapture.AddString(DeviceName[i]);
::GlobalFree((HGLOBAL)DeviceName[i]);
DeviceName[i] = NULL;
}
}
// 选择当前打开的视频采集设备
CHAR szVideoDeviceName[100] = {0};
BRAC_GetCurVideoCapture(szVideoDeviceName,sizeof(szVideoDeviceName));
m_cbVideoCapture.SelectString(-1,szVideoDeviceName);
// 刷新音频采集设备下拉列表
DeviceNum = 10;
BRAC_EnumAudioCapture(DeviceName,DeviceNum);
m_cbAudioCapture.ResetContent();
for(i=0; i<(INT)DeviceNum; i++)
{
if(DeviceName[i])
{
m_cbAudioCapture.AddString(DeviceName[i]);
::GlobalFree((HGLOBAL)DeviceName[i]);
DeviceName[i] = NULL;
}
}
// 选择当前打开的视频采集设备
CHAR szAudioDeviceName[100] = {0};
BRAC_GetCurAudioCapture(szAudioDeviceName,sizeof(szAudioDeviceName));
m_cbAudioCapture.SelectString(-1,szAudioDeviceName);
}
void CBRAnyChatSDKDemoDlg::OnSelchangeComboVideoCapture()
{
CString strCaptureName;
m_cbVideoCapture.GetLBText(m_cbVideoCapture.GetCurSel(),strCaptureName);
BRAC_SelectVideoCapture(strCaptureName);
}
void CBRAnyChatSDKDemoDlg::OnSelChangeComboAudioCapture()
{
CString strCaptureName;
m_cbAudioCapture.GetLBText(m_cbAudioCapture.GetCurSel(),strCaptureName);
BRAC_SelectAudioCapture(strCaptureName);
}
void CBRAnyChatSDKDemoDlg::OnSliderOutVolumeChange(NMHDR* pNMHDR, LRESULT* pResult)
{
DWORD dwVolume = m_ctrlOutVolume.GetPos();
BRAC_AudioSetVolume(BRAC_AD_WAVEOUT,dwVolume);
*pResult = 0;
}
void CBRAnyChatSDKDemoDlg::OnOnSliderInVolumeChange(NMHDR* pNMHDR, LRESULT* pResult)
{
DWORD dwVolume = m_ctrlInVolume.GetPos();
BRAC_AudioSetVolume(BRAC_AD_WAVEIN,dwVolume);
*pResult = 0;
}
// 录音的音量发生改变
void CBRAnyChatSDKDemoDlg::OnWaveInVolumeChange(DWORD dwVolume)
{
m_ctrlInVolume.SetPos(dwVolume);
}
// 放音的音量发生改变
void CBRAnyChatSDKDemoDlg::OnWaveOutVolumeChange(DWORD dwVolume)
{
m_ctrlOutVolume.SetPos(dwVolume);
}
void CBRAnyChatSDKDemoDlg::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case REFRESH_TRANSTASK_STATUS_TIMER: // 刷新缓冲区传输任务状态
{
if(m_dwTransTaskId == -1)
{
KillTimer(REFRESH_TRANSTASK_STATUS_TIMER);
break;
}
DWORD ret;
DWORD dwStatus = 0;
ret = BRAC_QueryTransTaskInfo(-1,m_dwTransTaskId,BRAC_TRANSTASK_STATUS,(PCHAR)&dwStatus,sizeof(DWORD));
if(ret != GV_ERR_SUCCESS)
{
KillTimer(REFRESH_TRANSTASK_STATUS_TIMER);
m_dwTransTaskId = -1;
SetDlgItemText(IDC_STATIC_FILESTATUS,"");
if(ret == GV_ERR_TRANSBUF_NOTASK)
AppendLogString("传输任务不存在,可能对方已离开房间!");
else
AppendLogString("查询任务信息失败!");
break;
}
DOUBLE dbProgress = 0.0;
BRAC_QueryTransTaskInfo(-1,m_dwTransTaskId,BRAC_TRANSTASK_PROGRESS,(PCHAR)&dbProgress,sizeof(DOUBLE));
DWORD dwBitrate = 0;
BRAC_QueryTransTaskInfo(-1,m_dwTransTaskId,BRAC_TRANSTASK_BITRATE,(PCHAR)&dwBitrate,sizeof(DWORD));
CString strStatus;
switch(dwStatus)
{
case 1: strStatus = "Ready"; break;
case 2: strStatus = "Process"; break;
case 3: strStatus = "Finish"; break;
case 4: strStatus = "Cancel"; break;
case 5: strStatus = "Reject"; break;
default: strStatus = "Unkonw"; break;
}
if(dwStatus == 3) // finish
{
KillTimer(REFRESH_TRANSTASK_STATUS_TIMER);
m_dwTransTaskId = -1;
AppendLogString("传输任务已完成!");
}
CString strBitrate;
if(dwBitrate >= 1000 * 1000)
strBitrate.Format("%.02f Mbps",(float)dwBitrate/1000/1000);
else if(dwBitrate >= 1000)
strBitrate.Format("%.02f Kbps",(float)dwBitrate/1000);
else
strBitrate.Format("%.02f bps",(float)dwBitrate);
CString strNotify;
strNotify.Format("%s-%.02f%%-%s",strStatus,dbProgress,strBitrate);
SetDlgItemText(IDC_STATIC_FILESTATUS,strNotify);
}
case REFRESH_SPEAKVOLUME_TIMER: // 刷新用户说话音量
{
DOUBLE fSpeakVolume = 0.0;
if(m_iUserID[0] != -1 && BRAC_QueryUserState(m_iUserID[0],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume0.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume0.SetPos(0);
fSpeakVolume = 0.0;
if(m_iUserID[1] != -1 && BRAC_QueryUserState(m_iUserID[1],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume1.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume1.SetPos(0);
fSpeakVolume = 0.0;
if(m_iUserID[2] != -1 && BRAC_QueryUserState(m_iUserID[2],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume2.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume2.SetPos(0);
fSpeakVolume = 0.0;
if(m_iUserID[3] != -1 && BRAC_QueryUserState(m_iUserID[3],BRAC_USERSTATE_SPEAKVOLUME,(PCHAR)&fSpeakVolume,sizeof(DOUBLE)) == GV_ERR_SUCCESS)
m_ctrlSpeakVolume3.SetPos((INT)fSpeakVolume);
else
m_ctrlSpeakVolume3.SetPos(0);
}
break;
case REFRESH_RECORDSTATE_TIMER: // 刷新录像状态
{
DWORD dwRecordState = 0;
if(m_iUserID[0] != -1 && BRAC_QueryUserState(m_iUserID[0],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE0)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
dwRecordState = 0;
if(m_iUserID[1] != -1 && BRAC_QueryUserState(m_iUserID[1],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE1)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
dwRecordState = 0;
if(m_iUserID[2] != -1 && BRAC_QueryUserState(m_iUserID[2],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE2)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
dwRecordState = 0;
if(m_iUserID[3] != -1 && BRAC_QueryUserState(m_iUserID[3],BRAC_USERSTATE_RECORDING,(PCHAR)&dwRecordState,sizeof(DWORD)) == GV_ERR_SUCCESS)
{
static BOOL bShow = FALSE;
bShow = dwRecordState ? !bShow : FALSE;
GetDlgItem(IDC_STATIC_RECORDSTATE3)->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
}
break;
default:
break;
}
CDialog::OnTimer(nIDEvent);
}
void CBRAnyChatSDKDemoDlg::OnButtonSendFile()
{
if(m_dwTransTaskId != -1) // 演示程序为了简洁,同时只允许传一个任务,实际上SDK是可以多任务并发的
return;
static TCHAR BASED_CODE szFilter[] = _T("All Files (*.*)||*.*\0");
CFileDialog dlg(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, szFilter, this);
if (dlg.DoModal() == IDOK)
{
CString strFileName = dlg.GetPathName();
DWORD dwTaskId = 0;
DWORD wParam = 1; // 上层应用程序可自定义wParam、lParam的值,这两个参数的值将被回调给对方
DWORD lParam = 2;
DWORD dwFlags = 0; // 该标志设置为0,则SDK将自动根据网络状态选择合适的传输途径(TCP、UDP or P2P)
DWORD ret = BRAC_TransFile(m_iUserID[1],strFileName.GetBuffer(0),wParam,lParam,dwFlags,dwTaskId);
if(ret == GV_ERR_SUCCESS)
{
m_dwTransTaskId = dwTaskId;
SetTimer(REFRESH_TRANSTASK_STATUS_TIMER,100,NULL);
}
else
{
CString strError;
strError.Format("创建文件传输任务失败,出错代码:%d",ret);
AppendLogString(strError);
SetDlgItemText(IDC_STATIC_FILESTATUS,"");
}
}
}
// 传输超大缓冲区任务演示
void CBRAnyChatSDKDemoDlg::OnButtonTransbuf()
{
if(m_dwTransTaskId != -1) // 演示程序为了简洁,同时只允许传一个任务,实际上SDK是可以多任务并发的
return;
PCHAR lpBuf = (PCHAR)malloc(10*1024); // 为了演示,创建一个10KByte大小的缓冲区
DWORD dwLen = 10*1024;
if(!lpBuf)
return;
lpBuf[1000] = 'Y'; // 演示的需要,为了验证收到的数据是否正确,在缓冲区中间某个位置设置一个标志,对方接收后,可判断该标志是否为设定值
DWORD dwTaskId = 0;
DWORD wParam = 3; // 上层应用程序可自定义wParam、lParam的值,这两个参数的值将被回调给对方
DWORD lParam = 4;
DWORD dwFlags = 0; // 该标志设置为0,则SDK将自动根据网络状态选择合适的传输途径(TCP、UDP or P2P)
DWORD ret = BRAC_TransBufferEx(m_iUserID[1],(PBYTE)lpBuf,dwLen,wParam,lParam,dwFlags,dwTaskId);
if(ret == GV_ERR_SUCCESS)
{
m_dwTransTaskId = dwTaskId;
SetTimer(REFRESH_TRANSTASK_STATUS_TIMER,100,NULL);
}
else
{
CString strError;
strError.Format("创建缓冲区传输任务失败,出错代码:%d",ret);
AppendLogString(strError);
SetDlgItemText(IDC_STATIC_FILESTATUS,"");
}
// 缓冲区调用完成后, 可以立即释放掉
free(lpBuf);
// BRAC_TransBuffer(m_iUserID[1],(LPBYTE)"bairuitech",10);
}
void CBRAnyChatSDKDemoDlg::OnCheckVad()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_VADCTRL,(PCHAR)&m_bEnableVAD,sizeof(m_bEnableVAD));
}
void CBRAnyChatSDKDemoDlg::OnCheckAgc()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_AGCCTRL,(PCHAR)&m_bEnableAGC,sizeof(m_bEnableAGC));
}
void CBRAnyChatSDKDemoDlg::OnCheckEcho()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_ECHOCTRL,(PCHAR)&m_bEnableEcho,sizeof(m_bEnableEcho));
}
void CBRAnyChatSDKDemoDlg::OnCheckNs()
{
UpdateData(TRUE);
BRAC_SetSDKOption(BRAC_SO_AUDIO_NSCTRL,(PCHAR)&m_bEnableNS,sizeof(m_bEnableNS));
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl0()
{
// 为了演示程序简单,这儿采用静态变量保存上一次的状态,可能不准确,因为可能在别的地方有打开,或是关闭的操作,下同
// 特别是当前用户离开房间,别的用户再进来时,初始状态将不准确
static BOOL bLastState = TRUE;
if(m_iUserID[0] != -1)
{
BRAC_UserCameraControl(m_iUserID[0],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl1()
{
static BOOL bLastState = TRUE;
if(m_iUserID[1] != -1)
{
BRAC_UserCameraControl(m_iUserID[1],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl2()
{
static BOOL bLastState = TRUE;
if(m_iUserID[2] != -1)
{
BRAC_UserCameraControl(m_iUserID[2],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonVideoctrl3()
{
static BOOL bLastState = TRUE;
if(m_iUserID[3] != -1)
{
BRAC_UserCameraControl(m_iUserID[3],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl0()
{
static BOOL bLastState = TRUE;
if(m_iUserID[0] != -1)
{
BRAC_UserSpeakControl(m_iUserID[0],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl1()
{
static BOOL bLastState = TRUE;
if(m_iUserID[1] != -1)
{
BRAC_UserSpeakControl(m_iUserID[1],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl2()
{
static BOOL bLastState = TRUE;
if(m_iUserID[2] != -1)
{
BRAC_UserSpeakControl(m_iUserID[2],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonAudioctrl3()
{
static BOOL bLastState = TRUE;
if(m_iUserID[3] != -1)
{
BRAC_UserSpeakControl(m_iUserID[3],!bLastState);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl0()
{
static BOOL bLastState = FALSE;
if(m_iUserID[0] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[0],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl1()
{
static BOOL bLastState = FALSE;
if(m_iUserID[1] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[1],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl2()
{
static BOOL bLastState = FALSE;
if(m_iUserID[2] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[2],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonRecordctrl3()
{
static BOOL bLastState = FALSE;
if(m_iUserID[3] != -1)
{
BRAC_StreamRecordCtrl(m_iUserID[3],!bLastState,0,0);
bLastState = !bLastState;
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl0()
{
if(m_iUserID[0] != -1)
{
BRAC_SnapShot(m_iUserID[0],0,0);
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl1()
{
if(m_iUserID[1] != -1)
{
BRAC_SnapShot(m_iUserID[1],0,0);
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl2()
{
if(m_iUserID[2] != -1)
{
BRAC_SnapShot(m_iUserID[2],0,0);
}
}
void CBRAnyChatSDKDemoDlg::OnButtonSnapshotctrl3()
{
if(m_iUserID[3] != -1)
{
BRAC_SnapShot(m_iUserID[3],0,0);
}
}
复制代码
文字信息交流
点对点语音、视频通话
多方语音、视频交互
文件传输
拍照、录像
自定义缓冲区传输
…………
P2P+服务器转发,UPnP支持
音视频同步,多路混音
回音消除、噪音抑制、自动增益
网络自适应,3G网络优化
动态缓冲区控制
视频防马赛克处理
发言模式、放歌模式、卡拉OK模式,单声道、立体声自动切换
相关推荐
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累... 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,本人不对所涉及的版权问题或内容负法律责任。如有侵权,请举报或通知本人删除。
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累... 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,本人不对所涉及的版权问题或内容负法律责任。如有侵权,请举报或通知本人删除。
"源码库.url"是一个快捷方式,指向源代码仓库,对于开发者来说,可以查看和学习源代码,甚至进行二次开发。 总的来说,这个压缩包提供的是一套完整的在线内容编辑解决方案,无论是图片编辑、视频处理还是版权保护,...
【3D游戏引擎源代码】是计算机编程领域中的一个核心话题,特别是在游戏开发中,它构成了游戏的基础架构。本项目是作者在大学时期(2010年)的作品,使用了Windows操作系统平台和DirectX 3D图形库进行开发。这展示了...
3. **音视频渲染过滤器**:将解码后的音视频数据输出到显示器或扬声器。 4. **转换过滤器**:可能包括视频和音频的格式转换,以适应渲染过滤器的需求。 5. **时间线控制器**:允许用户播放、暂停、停止和跳转到特定...
在这个“原创UDP聊天软件及源代码”项目中,开发者利用Java语言实现了基于UDP协议的聊天功能,包括群聊和点对点通信。 在UDP协议中,数据是以数据报的形式发送的,每个数据报都有完整的源和目标地址,以及长度和...
"极品山寨影音系统源码"是用易语言编写的多媒体播放器的源代码示例,对于初学者来说,这是一个很好的实践和学习资源。 首先,我们要理解什么是源码。源码,即程序的原始代码,是由程序员按照特定编程语言的语法书写...
2. **检查源代码**:如果音频是通过HTML5 `<audio>`标签嵌入的,可以在源代码中找到`src`属性链接,复制并下载。 3. **浏览器扩展**:和图片一样,也可以使用浏览器扩展来批量下载音频文件。 三、下载网页内的视频 ...
代码中将直播端和显示端分开两个文件,可以使用手机或电脑直播,在电脑或手机显示(比较灵活); 本人最近开发这块功能,有问题欢迎随时留言沟通~ PS:建议电脑使用百度浏览器,手机使用chrome浏览器 功能说明:...
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累... 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,本人不对所涉及的版权问题或内容负法律责任。如有侵权,请举报或通知本人删除。
这个"视频截取程序的源代码"提供了一种解决方案,能够帮助用户从视频中提取出特定的帧,以便进行进一步处理或保存。下面我们将深入探讨这个程序的工作原理、涉及的技术以及可能的应用场景。 首先,视频是由一系列...
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...
光影娱乐影音小程序源码是一个专为娱乐和影音播放设计的小程序源代码集合,适用于开发者进行二次开发或学习。源码的使用旨在促进技术交流,帮助编程爱好者深入理解小程序的架构和功能实现。在这个压缩包中,您将找到...
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...
VC++视频聊天系统源代码 实例简单,有用户登录、传输文件、视频、画质调节、禁音检测、回音消除、自动增益、噪音抑制、视频控制等、 VC++搜索指定文件夹中的文件 VC++文件分割、合并工具 自绘了Button、...
源码资源包是一种集合了各种类型的编程源代码的压缩文件,包括网站源码、行业源码、游戏源码、工具源码以及素材等。这样的资源包对于开发者、学习者和创业者来说都具有极高的价值,因为它们提供了丰富的参考资料和...
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...