📄 myendpoint.cpp
字号:
m_dlg.OnUserInput();
m_dlg.m_UserInputDlg.SetForegroundWindow();
}
}
//Called when finished registering with GK
void CMyEndPoint::OnUseGatekeeper(enum UseGKResult result,const char* name_GK)
{
m_dlg.Output("Finished registering with Gatekeeper,GKname=\"%s\",result=%s",name_GK,UseGKResultNames[result]);
if(result==RegistrationSuccessful)
{
//Success
CString s;
s.Format("Registered with gatekeeper \"%s\"",name_GK);
m_dlg.m_StatusBar.SetText(s,2,0);
}
else
m_dlg.m_StatusBar.SetText("No gatekeeper",2,0);
}
//Start to capture local video
BOOL CMyEndPoint::StartLocalVideo()
{
CConfig config;
BOOL bRet=FALSE;
int w,h;
if(m_VideoGrabber.IsOpened())
{
bRet=TRUE;
goto RET;
}
StopLocalVideo();
if(config.GetInteger(KEY_CAPTURE_FORMAT,VS_QCIF)==VS_QCIF)
{
w=176;
h=144;
}
else
{
w=352;
h=288;
}
//DirectShow is another choice for video capture
m_VideoGrabber.SetGrabberMode(config.GetBoolean(KEY_USE_DIRECTSHOW,FALSE)?VG_DS:VG_VFW);
//Open device
if(!m_VideoGrabber.Open(config.GetInteger(KEY_VIDEO_INPUT_DEVICE,0),config.GetInteger(KEY_CAPTURE_FPS,10)))
goto RET;
//Start
if(!m_VideoGrabber.StartStream(w,h))
goto RET;
bRet=TRUE;
RET:
if(!bRet)
StopLocalVideo();
return bRet;
}
//Stop capturing local video
BOOL CMyEndPoint::StopLocalVideo()
{
m_VideoGrabber.StopStream();
m_VideoGrabber.Close();
return TRUE;
}
//Start to render remote video
//
BOOL CMyEndPoint::StartRemoteVideo()
{
BOOL bRet=FALSE;
DWORD id;
if(m_hRemoteVideoThread)
{
bRet=TRUE;
goto RET;
}
StopRemoteVideo();
//Add a video channel with id=0 to video mixer
if(!m_VideoMixer.AddChannel(0,TRUE))
goto RET;
//
m_bStopRemoteVideoThread=FALSE;
//Create and start remote video rendering thread
m_hRemoteVideoThread=CreateThread(NULL,0,RemoteVideoThreadProc,this,0,&id);
if(m_hRemoteVideoThread==NULL)
goto RET;
bRet=TRUE;
RET:
if(!bRet)
StopRemoteVideo();
return bRet;
}
//Stop rendering remote video
BOOL CMyEndPoint::StopRemoteVideo()
{
if(m_hRemoteVideoThread)
{
m_bStopRemoteVideoThread=TRUE;
WaitForSingleObject(m_hRemoteVideoThread,INFINITE);
CloseHandle(m_hRemoteVideoThread);
m_hRemoteVideoThread=NULL;
}
m_VideoMixer.RemoveChannel(0,TRUE);
return TRUE;
}
//The thread proc for rendering remote video
DWORD WINAPI CMyEndPoint::RemoteVideoThreadProc(LPVOID param)
{
CMyEndPoint * pep=(CMyEndPoint*)param;
int w=352,h=288;//Always render a CIF frame
while(!pep->m_bStopRemoteVideoThread)
{
int local=0;
if(pep->m_VideoMixer.ChannelExist(0,FALSE))
local=1;
if(pep->m_VideoMixer.GetChannelCount(FALSE)-local>0)
{
//Get and lock the buffer
BYTE *p=pep->m_dlg.m_RemoteVideoWnd.GetBuffer(w,h);
if(p)
{
//Why not use delay in video mixer?
//The video buffer in remote video window has a mutex, and is locked
//until ReleaseBuffer called. We should read the video frame as soon
//as possible to avoid UI thread blocking.
pep->m_VideoMixer.Read(0,p,w,h,FALSE);
//Unlock the buffer
pep->m_dlg.m_RemoteVideoWnd.ReleaseBuffer();
}
//Just sleep a fixed period
Sleep(50);
}
else//No video incoming channel, so just sleep
Sleep(100);
}
return 0;
}
//Start to record local audio
BOOL CMyEndPoint::StartLocalAudio()
{
BOOL bRet=FALSE;
CConfig config;
if(m_hLocalAudioThread)
{
bRet=TRUE;
goto RET;
}
StopLocalAudio();
DWORD id;
//
if(!m_AudioMixer.AddChannel(0,FALSE))
goto RET;
//Open audio record device
if(!m_AudioRecorder.Open(config.GetInteger(KEY_AUDIO_INPUT_DEVICE,0)))
goto RET;
m_bStopLocalAudioThread=FALSE;
//Create a thread to audio record thread
m_hLocalAudioThread=CreateThread(NULL,0,LocalAudioThreadProc,this,0,&id);
if(m_hLocalAudioThread==NULL)
goto RET;
//The continuity of audio is improved by setting highest priority
SetThreadPriority(m_hLocalAudioThread,THREAD_PRIORITY_HIGHEST);
bRet=TRUE;
m_dlg.Output("Audio record thread started");
RET:
if(!bRet)
{
StopLocalAudio();
}
return bRet;
}
//Stop recording local audio
BOOL CMyEndPoint::StopLocalAudio()
{
if(m_hLocalAudioThread)
{
m_bStopLocalAudioThread=TRUE;
WaitForSingleObject(m_hLocalAudioThread,INFINITE);
CloseHandle(m_hLocalAudioThread);
m_hLocalAudioThread=NULL;
m_dlg.Output("Audio record thread ended");
}
m_AudioRecorder.Close();
m_AudioMixer.RemoveChannel(0,FALSE);
return TRUE;
}
//Start to playback remote audio
BOOL CMyEndPoint::StartRemoteAudio()
{
BOOL bRet=FALSE;
CConfig config;
DWORD id;
if(m_hRemoteAudioThread)
{
bRet=TRUE;
goto RET;
}
StopRemoteAudio();
if(!m_AudioMixer.AddChannel(0,TRUE))
goto RET;
//Open audio playback device
if(!m_AudioPlayer.Open(config.GetInteger(KEY_AUDIO_OUTPUT_DEVICE,0)))
goto RET;
m_bStopRemoteAudioThread=FALSE;
//Create audio playback thread
m_hRemoteAudioThread=CreateThread(NULL,0,RemoteAudioThreadProc,this,0,&id);
if(m_hRemoteAudioThread==NULL)
goto RET;
//The continuity of audio is improved by setting highest priority
SetThreadPriority(m_hRemoteAudioThread,THREAD_PRIORITY_HIGHEST);
bRet=TRUE;
m_dlg.Output("Audio playback thread started");
RET:
if(!bRet)
{
StopRemoteAudio();
}
return bRet;
}
//Stop playback remote audio
BOOL CMyEndPoint::StopRemoteAudio()
{
if(m_hRemoteAudioThread)
{
m_bStopRemoteAudioThread=TRUE;
WaitForSingleObject(m_hRemoteAudioThread,INFINITE);
CloseHandle(m_hRemoteAudioThread);
m_hRemoteAudioThread=NULL;
m_dlg.Output("Audio playback thread ended");
}
m_AudioPlayer.Close();
m_AudioMixer.RemoveChannel(0,TRUE);
return TRUE;
}
//The thread proc for playback remote audio
DWORD WINAPI CMyEndPoint::RemoteAudioThreadProc(LPVOID param)
{
CMyEndPoint * pep=(CMyEndPoint*)param;
//Just set a fixed buffer size
BYTE buffer[480];
while(!pep->m_bStopRemoteAudioThread)
{
if(pep->m_AudioMixer.GetChannelCount(FALSE)>0)
{
//Get the audio data only when needed
if(pep->m_AudioMixer.Read(0,buffer,480,FALSE))
{
//Playback the audio data
pep->m_AudioPlayer.Write(buffer,480);
}
else
break;
}
else//Sleep a while
Sleep(10);
}
return 0;
}
//The thread proc for record local audio
DWORD WINAPI CMyEndPoint::LocalAudioThreadProc(LPVOID param)
{
CMyEndPoint * pep=(CMyEndPoint*)param;
//Just set a fixed buffer size
BYTE buffer[480];
DWORD signalLvl=0;
DWORD count=0;
while(!pep->m_bStopLocalAudioThread)
{
if(pep->m_AudioMixer.GetChannelCount(TRUE)>0)
{
//Get the audio data only when needed
if(pep->m_AudioRecorder.Read(buffer,480))
{
DWORD *p=NULL;
if(count%4==0)//Get audio signal only every 4 frames
p=&signalLvl;
pep->m_AudioMixer.Write(0,buffer,480,FALSE,p);
if(p!=NULL)//Set a progress bar to show MIC signal
pep->m_dlg.m_micVolume.PostMessage(PBM_SETPOS,*p);
count++;
}
else
break;
}
else
Sleep(10);
}
pep->m_dlg.m_micVolume.PostMessage(PBM_SETPOS,0);
return 0;
}
/////////////////////////////////////////
CMyILSClient::CMyILSClient(CILSClientWnd &IlsWnd):m_IlsWnd(IlsWnd)
{
}
CMyILSClient::~CMyILSClient()
{
}
void CMyILSClient::OnEnumUserNames(DWORD id, DWORD result, const char *name)
{
}
void CMyILSClient::OnEnumUsers(DWORD id, DWORD result, USER_INFO &ui)
{
if(result==S_OK)
m_IlsWnd.InsertItem(&ui);
else
m_IlsWnd.m_btnRefresh.EnableWindow();
}
void CMyILSClient::OnGetUserInfo(DWORD id, DWORD result, USER_INFO &ui)
{
}
void CMyILSClient::OnRegister(DWORD id, DWORD result)
{
if(result==S_OK)
{
m_IlsWnd.m_btnRegister.SetWindowText("Unregister");
}
m_IlsWnd.m_btnRegister.EnableWindow();
}
void CMyILSClient::OnUnregister(DWORD id, DWORD result)
{
if(result==S_OK)
{
m_IlsWnd.m_btnRegister.SetWindowText("Register");
}
m_IlsWnd.m_btnRegister.EnableWindow();
}
void CMyILSClient::OnUpdate(DWORD id, DWORD result)
{
m_IlsWnd.m_btnUpdate.EnableWindow();
}
void CMyILSClient::OnUserStateChanged(DWORD state, const char *server)
{
if(state==ILS_UNREGISTERED)
{
m_IlsWnd.m_btnRegister.SetWindowText("Register");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -