From 623b79fb6026507c24df5c6cffdd983282d481a3 Mon Sep 17 00:00:00 2001 From: "chenyuguo@agora.io" Date: Mon, 9 Jun 2025 18:30:33 +0800 Subject: [PATCH] [feat]4.6.0 windows --- windows/APIExample/APIExample/APIExample.rc | 46 +- .../APIExample/APIExample/APIExample.vcxproj | 8 + .../APIExample/APIExample.vcxproj.filters | 39 ++ .../APIExample/APIExample/APIExampleDlg.cpp | 42 +- windows/APIExample/APIExample/APIExampleDlg.h | 6 + .../Advanced/AudioEffect/CAgoraEffectDlg.cpp | 2 +- .../AudioMixing/CAgoraAudioMixingDlg.cpp | 2 +- .../AudioProfile/CAgoraAudioProfile.cpp | 2 +- .../AudioVolume/CAgoraAudioVolumeDlg.cpp | 2 +- .../Advanced/Beauty/CAgoraBeautyDlg.cpp | 2 +- .../APIExample/Advanced/Beauty/CDlgBeauty.cpp | 2 +- .../Advanced/Beauty2.0/CDlgBeauty2.0.cpp | 536 +++++++++++++++ .../Advanced/Beauty2.0/CDlgBeauty2.0.h | 143 ++++ .../Advanced/Beauty2.0/CDlgBeautyEx2.0.cpp | 381 +++++++++++ .../Advanced/Beauty2.0/CDlgBeautyEx2.0.h | 165 +++++ .../BeautyAudio/CAgoraBeautyAudio.cpp | 2 +- .../CrossChannel/CAgoraCrossChannelDlg.cpp | 2 +- .../CAgoraCaptureAudioDlg.cpp | 2 +- .../CustomEncrypt/CAgoraCustomEncryptDlg.cpp | 2 +- .../CAgoraCaptureVideoDlg.cpp | 2 +- .../FaceCapture/CAgoraFaceCaptureDlg.cpp | 2 +- .../CLocalVideoTranscodingDlg.cpp | 2 +- .../MediaEncrypt/CAgoraMediaEncryptDlg.cpp | 2 +- .../MediaPlayer/CAgoraMediaPlayer.cpp | 2 +- .../MediaRecorder/CAgoraMediaRecorder.cpp | 2 +- .../Advanced/Metadata/CAgoraMetaDataDlg.cpp | 6 +- .../Advanced/MultiCamera/CMultiCameraDlg.cpp | 2 +- .../MultiChannel/CAgoraMultiChannelDlg.cpp | 2 +- .../CAgoraMutilVideoSourceDlg.cpp | 2 +- .../MultiVideoSourceTracks.cpp | 4 +- .../Advanced/Multipath/CMultipathDlg.cpp | 537 +++++++++++++++ .../Advanced/Multipath/CMultipathDlg.h | 107 +++ .../OriginalAudio/CAgoraOriginalAudioDlg.cpp | 2 +- .../OriginalVideo/CAgoraOriginalVideoDlg.cpp | 2 +- .../PreCallTest/CAgoraPreCallTestDlg.cpp | 174 ++--- .../PushExternalVideoYUV.cpp | 2 +- .../RTMPStream/AgoraRtmpStreaming.cpp | 2 +- .../RTMPinject/AgoraRtmpInjectionDlg.cpp | 28 +- .../RegionConn/CAgoraRegionConnDlg.cpp | 2 +- .../ReportInCall/CAgoraReportInCallDlg.cpp | 2 +- .../ScreenShare/AgoraScreenCapture.cpp | 2 +- .../Advanced/Simulcast/CSimulcastDlg.cpp | 640 ++++++++++++++++++ .../Advanced/Simulcast/CSimulcastDlg.h | 121 ++++ .../SpatialAudio/CAgoraSpatialAudioDlg.cpp | 2 +- .../TransparentBg/TransparentBgDialog.cpp | 2 +- .../CJoinChannelVideoByTokenDlg.cpp | 6 +- .../LiveBroadcasting/CLiveBroadcastingDlg.cpp | 2 +- windows/APIExample/APIExample/Language.h | 4 + windows/APIExample/APIExample/en.ini | 4 +- windows/APIExample/APIExample/resource.h | 24 +- windows/APIExample/APIExample/stdafx.cpp | 9 +- windows/APIExample/APIExample/stdafx.h | 3 +- windows/APIExample/APIExample/zh-cn.ini | 6 +- 53 files changed, 2945 insertions(+), 152 deletions(-) create mode 100644 windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.cpp create mode 100644 windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.h create mode 100644 windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.cpp create mode 100644 windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.h create mode 100644 windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.cpp create mode 100644 windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.h create mode 100644 windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.cpp create mode 100644 windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.h diff --git a/windows/APIExample/APIExample/APIExample.rc b/windows/APIExample/APIExample/APIExample.rc index 8efcfb2cc..7c2095e59 100755 --- a/windows/APIExample/APIExample/APIExample.rc +++ b/windows/APIExample/APIExample/APIExample.rc @@ -17,7 +17,7 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// 中文(简体,中国) resources +// 锟斤拷锟斤拷(锟斤拷锟藉,锟叫癸拷) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED @@ -839,6 +839,44 @@ BEGIN CONTROL "",IDC_SLIDER__SHAPE_AREA_INTENSITY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,346,35,100,15 END +IDD_DIALOG_MULTIPATH DIALOGEX 0, 0, 632, 400 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Role:",IDC_STATIC_ROLE,14,14,25,8 + COMBOBOX IDC_COMBO_ROLE,45,12,80,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Channel:",IDC_STATIC_CHANNELNAME,14,35,35,8 + EDITTEXT IDC_EDIT_CHANNELNAME,55,33,100,14,ES_AUTOHSCROLL + PUSHBUTTON "Join Channel",IDC_BUTTON_JOINCHANNEL,170,32,70,16 + LTEXT "Multipath Mode:",IDC_STATIC_MULTIPATH_MODE,14,56,60,8 + COMBOBOX IDC_COMBO_MULTIPATH_MODE,80,54,80,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Enable Multipath:",IDC_STATIC_ENABLE_MULTIPATH,170,56,60,8 + CONTROL "",IDC_CHECK_ENABLE_MULTIPATH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,240,55,15,10 + CONTROL "",IDC_STATIC_VIDEO,"Static",SS_BLACKFRAME,14,80,400,200 + LISTBOX IDC_LIST_INFO_MULTIPATH,430,80,180,200,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + +IDD_DIALOG_SIMULCAST DIALOGEX 0, 0, 632, 400 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "",IDC_STATIC_VIDEO,0,0,483,283 + LISTBOX IDC_LIST_INFO_SIMULCAST,495,0,137,283,LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_ROLE,52,323,60,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Client Role",IDC_STATIC_ROLE,7,324,41,10 + LTEXT "Channel Name",IDC_STATIC_CHANNELNAME,16,298,48,8 + EDITTEXT IDC_EDIT_CHANNELNAME,75,296,129,12,ES_AUTOHSCROLL + PUSHBUTTON "JoinChannel",IDC_BUTTON_JOINCHANNEL,211,295,50,14 + + LTEXT "Simulcast Layers:",IDC_STATIC_LAYER_TITLE,130,324,70,8 + CONTROL "Layer 1 (High)",IDC_CHECK_LAYER1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,320,70,10 + CONTROL "Layer 2 (Medium)",IDC_CHECK_LAYER2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,290,320,80,10 + CONTROL "Layer 3 (Low)",IDC_CHECK_LAYER3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,335,70,10 + CONTROL "Layer 4 (Ultra Low)",IDC_CHECK_LAYER4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,290,335,80,10 + + LTEXT "Select Layer:",IDC_STATIC_LAYER_SELECT,130,324,50,8 + COMBOBOX IDC_COMBO_LAYER_SELECT,190,322,80,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END ///////////////////////////////////////////////////////////////////////////// // @@ -1374,12 +1412,12 @@ IDR_TEST_WAVE WAVE "res\\ID_TEST_AUDIO.wav" IDR_WAVE1 WAVE "res\\audiomixing.wav" -#endif // 中文(简体,中国) resources +#endif // 锟斤拷锟斤拷(锟斤拷锟藉,锟叫癸拷) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// 英语(美国) resources +// 英锟斤拷(锟斤拷锟斤拷) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US @@ -1505,7 +1543,7 @@ BEGIN IDS_ABOUTBOX "&About APIExample..." END -#endif // 英语(美国) resources +#endif // 英锟斤拷(锟斤拷锟斤拷) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/windows/APIExample/APIExample/APIExample.vcxproj b/windows/APIExample/APIExample/APIExample.vcxproj index f165aabe2..e64e4d296 100644 --- a/windows/APIExample/APIExample/APIExample.vcxproj +++ b/windows/APIExample/APIExample/APIExample.vcxproj @@ -280,8 +280,12 @@ if exist $(SolutionDir)APIExample\res\hdr_1280_720.yuv (copy $(SolutionDir)APIEx + + + + @@ -294,6 +298,7 @@ if exist $(SolutionDir)APIExample\res\hdr_1280_720.yuv (copy $(SolutionDir)APIEx + @@ -306,6 +311,7 @@ if exist $(SolutionDir)APIExample\res\hdr_1280_720.yuv (copy $(SolutionDir)APIEx + @@ -351,6 +357,7 @@ if exist $(SolutionDir)APIExample\res\hdr_1280_720.yuv (copy $(SolutionDir)APIEx + @@ -363,6 +370,7 @@ if exist $(SolutionDir)APIExample\res\hdr_1280_720.yuv (copy $(SolutionDir)APIEx + diff --git a/windows/APIExample/APIExample/APIExample.vcxproj.filters b/windows/APIExample/APIExample/APIExample.vcxproj.filters index b012a6003..bc67fbe4b 100644 --- a/windows/APIExample/APIExample/APIExample.vcxproj.filters +++ b/windows/APIExample/APIExample/APIExample.vcxproj.filters @@ -118,6 +118,15 @@ {2a74c488-9982-4577-8594-8320c71beb6d} + + {221f9de2-f7b5-4d9f-8275-a660d1259cf0} + + + {97807267-2591-43c9-b24c-03042bf71158} + + + {3be0c114-2815-4e14-885d-a666411338db} + @@ -282,6 +291,18 @@ Advanced\Beauty + + Advanced\Beauty2.0 + + + Advanced\Beauty2.0 + + + Advanced\Multipath + + + Advanced\Simulcast + @@ -440,6 +461,24 @@ Source Files + + Source Files + + + Advanced\Beauty2.0 + + + Advanced\Beauty2.0 + + + Source Files + + + Advanced\Multipath + + + Advanced\Simulcast + diff --git a/windows/APIExample/APIExample/APIExampleDlg.cpp b/windows/APIExample/APIExample/APIExampleDlg.cpp index bf0030260..a18d54388 100755 --- a/windows/APIExample/APIExample/APIExampleDlg.cpp +++ b/windows/APIExample/APIExample/APIExampleDlg.cpp @@ -1,4 +1,3 @@ - // APIExampleDlg.cpp : implementation file // @@ -250,6 +249,7 @@ void CAPIExampleDlg::InitSceneDialog() m_vecAdvanced.push_back(advancedMediaEncrypt); m_vecAdvanced.push_back(AdvancedLocalVideoTranscoding); m_vecAdvanced.push_back(beautyFace); + m_vecAdvanced.push_back(beautyFace2); m_vecAdvanced.push_back(advancedBeautyAudio); m_vecAdvanced.push_back(SpatialAudio); m_pMultiChannelDlg = new CAgoraMultiChannelDlg(&m_staMainArea); @@ -259,6 +259,8 @@ void CAPIExampleDlg::InitSceneDialog() //transparent bg m_vecAdvanced.push_back(TransparentBackground); m_vecAdvanced.push_back(RteUrlPlayer); + m_vecAdvanced.push_back(Multipath); + m_vecAdvanced.push_back(advancedSimulcast); //inject m_pRtmpInjectDlg = new CAgoraRtmpInjectionDlg(&m_staMainArea); @@ -374,6 +376,10 @@ void CAPIExampleDlg::InitSceneDialog() m_pDlgBeauty->Create(CDlgBeauty::IDD); m_pDlgBeauty->MoveWindow(&rcWnd); + m_pDlgBeauty2 = new CDlgBeauty2(&m_staMainArea); + m_pDlgBeauty2->Create(CDlgBeauty2::IDD); + m_pDlgBeauty2->MoveWindow(&rcWnd); + // spatial audio m_pSpatialAudioDlg = new CAgoraSpatialAudioDlg(&m_staMainArea); @@ -401,6 +407,16 @@ void CAPIExampleDlg::InitSceneDialog() m_RtePlayer = new CRtePlayerDlg(&m_staMainArea); m_RtePlayer->Create(CRtePlayerDlg::IDD); m_RtePlayer->MoveWindow(&rcWnd); + + // mulit path + m_pMultipathDlg = new CMultipathDlg(&m_staMainArea); + m_pMultipathDlg->Create(CMultipathDlg::IDD); + m_pMultipathDlg->MoveWindow(&rcWnd); + + // simulcast + m_pSimulcastDlg = new CSimulcastDlg(&m_staMainArea); + m_pSimulcastDlg->Create(CSimulcastDlg::IDD); + m_pSimulcastDlg->MoveWindow(&rcWnd); } @@ -640,6 +656,10 @@ void CAPIExampleDlg::CreateScene(CTreeCtrl& treeScene, CString selectedText) m_pDlgBeauty->InitAgora(); m_pDlgBeauty->ShowWindow(SW_SHOW); } + else if (selectedText.Compare(beautyFace2) == 0) { + m_pDlgBeauty2->InitAgora(); + m_pDlgBeauty2->ShowWindow(SW_SHOW); + } else if (selectedText.Compare(SpatialAudio) == 0) { m_pSpatialAudioDlg->InitAgora(); m_pSpatialAudioDlg->ShowWindow(SW_SHOW); @@ -656,6 +676,14 @@ void CAPIExampleDlg::CreateScene(CTreeCtrl& treeScene, CString selectedText) m_RtePlayer->InitAgora(); m_RtePlayer->ShowWindow(SW_SHOW); } + else if (selectedText.Compare(Multipath) == 0) { + m_pMultipathDlg->InitAgora(); + m_pMultipathDlg->ShowWindow(SW_SHOW); + } + else if (selectedText.Compare(advancedSimulcast) == 0) { + m_pSimulcastDlg->InitAgora(); + m_pSimulcastDlg->ShowWindow(SW_SHOW); + } //Sleep(500); } @@ -777,6 +805,10 @@ void CAPIExampleDlg::ReleaseScene(CTreeCtrl& treeScene, HTREEITEM& hSelectItem) m_pDlgBeauty->UnInitAgora(); m_pDlgBeauty->ShowWindow(SW_HIDE); } + else if (str.Compare(beautyFace2) == 0) { + m_pDlgBeauty2->UnInitAgora(); + m_pDlgBeauty2->ShowWindow(SW_HIDE); + } else if (str.Compare(SpatialAudio) == 0) { m_pSpatialAudioDlg->UnInitAgora(); m_pSpatialAudioDlg->ShowWindow(SW_HIDE); @@ -793,6 +825,14 @@ void CAPIExampleDlg::ReleaseScene(CTreeCtrl& treeScene, HTREEITEM& hSelectItem) m_RtePlayer->UnInitAgora(); m_RtePlayer->ShowWindow(SW_HIDE); } + else if (str.Compare(Multipath) == 0) { + m_pMultipathDlg->UnInitAgora(); + m_pMultipathDlg->ShowWindow(SW_HIDE); + } + else if (str.Compare(advancedSimulcast) == 0) { + m_pSimulcastDlg->UnInitAgora(); + m_pSimulcastDlg->ShowWindow(SW_HIDE); + } //Sleep(500); } diff --git a/windows/APIExample/APIExample/APIExampleDlg.h b/windows/APIExample/APIExample/APIExampleDlg.h index af7a753ed..1f3a9571b 100755 --- a/windows/APIExample/APIExample/APIExampleDlg.h +++ b/windows/APIExample/APIExample/APIExampleDlg.h @@ -27,6 +27,7 @@ #include "Advanced/MediaPlayer/CAgoraMediaPlayer.h" #include "Advanced/LocalVideoTranscoding/CLocalVideoTranscodingDlg.h" #include "Advanced/Beauty/CDlgBeauty.h" +#include "Advanced/Beauty2.0/CDlgBeauty2.0.h" #include "Advanced/BeautyAudio/CAgoraBeautyAudio.h" #include "Advanced/SpatialAudio/CAgoraSpatialAudioDlg.h" #include "Advanced/MediaRecorder/CAgoraMediaRecorder.h" @@ -36,6 +37,8 @@ #include "Advanced/TransparentBg/TransparentBgDialog.h" #include "Advanced/RtePlayer/RtePlayerDlg.h" #include "Advanced/CrossChannel/CAgoraCrossChannelDlg.h" +#include "Advanced/Multipath/CMultipathDlg.h" +#include "Advanced/Simulcast/CSimulcastDlg.h" #include #include #include @@ -111,7 +114,10 @@ class CAPIExampleDlg : public CDialogEx MultiVideoSourceTracks *m_pMultiVideoSourceTracks = nullptr; CAgoraFaceCaptureDlg *m_pAgoraFaceCaptureDlg = nullptr; CAgoraCrossChannelDlg *m_pAgoraCrossChannelDlg = nullptr; + CMultipathDlg *m_pMultipathDlg = nullptr; + CSimulcastDlg *m_pSimulcastDlg = nullptr; CDlgBeauty * m_pDlgBeauty = nullptr; + CDlgBeauty2 * m_pDlgBeauty2 = nullptr; CTransparentBgDlg* m_TransparentDlg = nullptr; CRtePlayerDlg* m_RtePlayer = nullptr; CString m_preSelectedItemText = _T(""); diff --git a/windows/APIExample/APIExample/Advanced/AudioEffect/CAgoraEffectDlg.cpp b/windows/APIExample/APIExample/Advanced/AudioEffect/CAgoraEffectDlg.cpp index f493b6602..f61b85925 100644 --- a/windows/APIExample/APIExample/Advanced/AudioEffect/CAgoraEffectDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/AudioEffect/CAgoraEffectDlg.cpp @@ -162,7 +162,7 @@ void CAgoraEffectDlg::UnInitAgora() m_rtcEngine->disableVideo(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; } diff --git a/windows/APIExample/APIExample/Advanced/AudioMixing/CAgoraAudioMixingDlg.cpp b/windows/APIExample/APIExample/Advanced/AudioMixing/CAgoraAudioMixingDlg.cpp index 70fc52d84..20b6bb515 100755 --- a/windows/APIExample/APIExample/Advanced/AudioMixing/CAgoraAudioMixingDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/AudioMixing/CAgoraAudioMixingDlg.cpp @@ -100,7 +100,7 @@ void CAgoraAudioMixingDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/AudioProfile/CAgoraAudioProfile.cpp b/windows/APIExample/APIExample/Advanced/AudioProfile/CAgoraAudioProfile.cpp index aee3bab02..b3a57f402 100644 --- a/windows/APIExample/APIExample/Advanced/AudioProfile/CAgoraAudioProfile.cpp +++ b/windows/APIExample/APIExample/Advanced/AudioProfile/CAgoraAudioProfile.cpp @@ -122,7 +122,7 @@ void CAgoraAudioProfile::UnInitAgora() // release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/AudioVolume/CAgoraAudioVolumeDlg.cpp b/windows/APIExample/APIExample/Advanced/AudioVolume/CAgoraAudioVolumeDlg.cpp index f710936a3..775f806b2 100644 --- a/windows/APIExample/APIExample/Advanced/AudioVolume/CAgoraAudioVolumeDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/AudioVolume/CAgoraAudioVolumeDlg.cpp @@ -118,7 +118,7 @@ void CAgoraAudioVolumeDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/Beauty/CAgoraBeautyDlg.cpp b/windows/APIExample/APIExample/Advanced/Beauty/CAgoraBeautyDlg.cpp index c5b35ecdf..f90d35e5f 100644 --- a/windows/APIExample/APIExample/Advanced/Beauty/CAgoraBeautyDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/Beauty/CAgoraBeautyDlg.cpp @@ -87,7 +87,7 @@ void CAgoraBeautyDlg::UnInitAgora() m_rtcEngine->disableVideo(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; } diff --git a/windows/APIExample/APIExample/Advanced/Beauty/CDlgBeauty.cpp b/windows/APIExample/APIExample/Advanced/Beauty/CDlgBeauty.cpp index 07c42010d..a3610f6ec 100755 --- a/windows/APIExample/APIExample/Advanced/Beauty/CDlgBeauty.cpp +++ b/windows/APIExample/APIExample/Advanced/Beauty/CDlgBeauty.cpp @@ -242,7 +242,7 @@ void CDlgBeauty::UnInitAgora() //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } diff --git a/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.cpp b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.cpp new file mode 100644 index 000000000..5a01f04e7 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.cpp @@ -0,0 +1,536 @@ +// CDlgBeauty.cpp: +// + +#include "stdafx.h" +#include "APIExample.h" +#include "CDlgBeauty2.0.h" +#include "afxdialogex.h" + +// CDlgBeauty + +IMPLEMENT_DYNAMIC(CDlgBeauty2, CDialogEx) + +CDlgBeauty2::CDlgBeauty2(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_DIALOG_BEAUTY, pParent) +{ + mBeautyDlgEx = new CDlgBeautyEx2(); +} + +CDlgBeauty2::~CDlgBeauty2() +{ + if (mBeautyDlgEx) + { + delete mBeautyDlgEx; + mBeautyDlgEx = nullptr; + } + +} + +void CDlgBeauty2::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_STATIC_CHANNELNAME, m_staChannel); + DDX_Control(pDX, IDC_EDIT_CHANNELNAME, m_edtChannel); + DDX_Control(pDX, IDC_BUTTON_JOINCHANNEL, m_btnJoinChannel); + DDX_Control(pDX, IDC_CHECK_BEAUTY_ENABLE, m_chkBeauty); + DDX_Control(pDX, IDC_STATIC_BEAUTY_LIGHTENING_CONTRAST_LEVEL, m_staContrast); + DDX_Control(pDX, IDC_STATIC_BEAUTY_REDNESS, m_staRedness); + DDX_Control(pDX, IDC_STATIC_BEAUTY_SMOOTHNESS, m_staSmoothness); + DDX_Control(pDX, IDC_STATIC_BEAUTY_LIGHTENING, m_staLightening); + DDX_Control(pDX, IDC_CHECK_ENHANCE, m_chkEnhance); + DDX_Control(pDX, IDC_SLIDER_STRENGTH, m_sldLength); + DDX_Control(pDX, IDC_STATIC_SKIN_PROTECT, m_staSkin); + DDX_Control(pDX, IDC_SLIDER_SKIN_PROTECT, m_sldSkin); + DDX_Control(pDX, IDC_CHECK_VIDEO_DENOISE, m_chkVideoDenoise); + DDX_Control(pDX, IDC_CHECK_VIDEO_DENOISE2, m_chkVirtual); + DDX_Control(pDX, IDC_CHECK_LOWLIGHT, m_chkLowlight); + DDX_Control(pDX, IDC_SLIDER_LIGHTENING, m_sdlLightening); + DDX_Control(pDX, IDC_SLIDER_REDNESS, m_sldRedness); + DDX_Control(pDX, IDC_SLIDER_SMOOTHNESS, m_sldSmoothness); + DDX_Control(pDX, IDC_LIST_INFO_BROADCASTING, m_lstInfo); + DDX_Control(pDX, IDC_STATIC_VIDEO, m_staVideoArea); + DDX_Control(pDX, IDC_COMBO_BEAUTE_LIGHTENING_CONTRAST_LEVEL, m_cmbContrast); + DDX_Control(pDX, IDC_RADIO_VIRTUAL_BG_BLUR, m_radioVirtualBgBlur); + DDX_Control(pDX, IDC_RADIO_VIRTUAL_BG_COLOR, m_radioVirtualBgColor); + DDX_Control(pDX, IDC_RADIO_VIRTUAL_BG_IMAGE, m_radioVirtualBgImage); + DDX_Control(pDX, IDC_RADIO_VIRTUAL_BG_VIDEO, m_radioVirtualBgVideo); + DDX_Control(pDX, IDC_SLIDER_BRIHTNESS, mSliderBright); + DDX_Control(pDX, IDC_CHECK_EXTENTION, mCkExtention); +} + + +BEGIN_MESSAGE_MAP(CDlgBeauty2, CDialogEx) + ON_BN_CLICKED(IDC_BUTTON_JOINCHANNEL, &CDlgBeauty2::OnBnClickedButtonJoinchannel) + ON_MESSAGE(WM_MSGID(EID_LEAVE_CHANNEL), &CDlgBeauty2::OnEIDLeaveChannel) + ON_MESSAGE(WM_MSGID(EID_JOINCHANNEL_SUCCESS), &CDlgBeauty2::OnEIDJoinChannelSuccess) + ON_BN_CLICKED(IDC_CHECK_BEAUTY_ENABLE, &CDlgBeauty2::OnBnClickedCheckBeautyEnable) + ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_REDNESS, &CDlgBeauty2::OnNMCustomdrawSliderRedness) + ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_LIGHTENING, &CDlgBeauty2::OnThumbposchangingSliderLightening) + ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_SMOOTHNESS, &CDlgBeauty2::OnNMCustomdrawSliderSmoothness) + ON_CBN_SELCHANGE(IDC_COMBO_BEAUTE_LIGHTENING_CONTRAST_LEVEL, &CDlgBeauty2::OnSelchangeComboBeauteLighteningContrastLevel) + ON_BN_CLICKED(IDC_CHECK_ENHANCE, &CDlgBeauty2::OnBnClickedCheckEnhance) + ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_STRENGTH, &CDlgBeauty2::OnCustomdrawSliderStrength) + ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_SKIN_PROTECT, &CDlgBeauty2::OnCustomdrawSliderSkinProtect) + ON_BN_CLICKED(IDC_CHECK_VIDEO_DENOISE, &CDlgBeauty2::OnBnClickedCheckVideoDenoise) + ON_BN_CLICKED(IDC_CHECK_VIDEO_DENOISE2, &CDlgBeauty2::OnBnClickedCheckVideoDenoise2) + ON_BN_CLICKED(IDC_CHECK_LOWLIGHT, &CDlgBeauty2::OnBnClickedCheckLowlight) + ON_WM_SHOWWINDOW() + ON_CONTROL_RANGE(BN_CLICKED, IDC_RADIO_VIRTUAL_BG_BLUR, IDC_RADIO_VIRTUAL_BG_IMAGE, &CDlgBeauty2::OnBnClickedStaticVirtualBgChoose) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER_BRIHTNESS, &CDlgBeauty2::OnNMCustomdrawSliderBrihtness) + ON_BN_CLICKED(IDC_CHECK_EXTENTION, &CDlgBeauty2::OnBnClickedCheckExtention) +END_MESSAGE_MAP() + + +// CDlgBeauty message hand;er + + +void CDlgBeauty2::OnBnClickedButtonJoinchannel() +{ + if (!m_joinChannel) { + CString strChannelName; + m_edtChannel.GetWindowText(strChannelName); + std::string szChannelId = cs2utf8(strChannelName); + if (strChannelName.IsEmpty()) { + AfxMessageBox(_T("Fill channel name first")); + return; + } + CString strInfo; + agora::rtc::Rectangle rect; + auto params = agora::rtc::ScreenCaptureParameters(640, 360, 15, 800); + + RECT rc; + ::GetWindowRect(GetDesktopWindow()->GetSafeHwnd(), &rc); + rect = { rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top }; + + //setup local video in the engine to canvas. + agora::rtc::VideoCanvas canvas; + canvas.renderMode = media::base::RENDER_MODE_FIT; + canvas.uid = 0; + canvas.view = m_videoWnds[0].GetSafeHwnd(); + canvas.sourceType = VIDEO_SOURCE_TRANSCODED; + canvas.mirrorMode = VIDEO_MIRROR_MODE_DISABLED; + m_rtcEngine->setupLocalVideo(canvas); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("setupLocalVideo")); + + //join channel + agora::rtc::ChannelMediaOptions op; + op.publishCameraTrack = true; + op.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING; + op.clientRoleType = agora::rtc::CLIENT_ROLE_BROADCASTER; + if (0 == m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.data(), 0, op)) { + strInfo.Format(_T("join channel %s, use ChannelMediaOptions"), strChannelName); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + } + + m_btnJoinChannel.SetWindowText(commonCtrlLeaveChannel); + } + else { + //leave channel + m_rtcEngine->leaveChannel(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("leave channel")); + //stop preview + //m_rtcEngine->stopPreview(); + //m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("stop preview")); + //m_btnJoinChannel.SetWindowText(commonCtrlJoinChannel); + } + m_joinChannel = !m_joinChannel; +} + +void CDlgBeauty2::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialogEx::OnShowWindow(bShow, nStatus); + + if (bShow) { + //init control text. + InitCtrlText(); + mBeautyDlgEx->InitCtrlText(); + } + else { + //resume window status. + ResumeStatus(); + if (mBeautyDlgEx) + { + mCkExtention.SetCheck(false); + mBeautyDlgEx->ShowWindow(SW_HIDE); + } + } +} + +bool CDlgBeauty2::InitAgora() +{ + //create Agora RTC engine + m_rtcEngine = createAgoraRtcEngine(); + if (!m_rtcEngine) { + m_lstInfo.InsertString(m_lstInfo.GetCount() - 1, _T("createAgoraRtcEngine failed")); + return false; + } + m_eventHandler.SetMsgReceiver(m_hWnd); + agora::rtc::RtcEngineContext context; + std::string strAppID = GET_APP_ID; + context.appId = strAppID.c_str(); + context.eventHandler = &m_eventHandler; + //set channel profile in the engine to the CHANNEL_PROFILE_LIVE_BROADCASTING. + context.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING; + //initialize the Agora RTC engine context. + int ret = m_rtcEngine->initialize(context); + if (ret != 0) { + m_initialize = false; + CString strInfo; + strInfo.Format(_T("initialize failed: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + return false; + } + else + m_initialize = true; + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("initialize success")); + + + CString strInfo; + ret = m_rtcEngine->enableExtension("agora_video_filters_clear_vision", "clear_vision", true); + strInfo.Format(_T("enableExtension: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("agora_video_filters_clear_vision")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("clear_vision")); + //enable video in the engine. + m_rtcEngine->enableVideo(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("enable video")); + + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("live broadcasting")); + //set client role in the engine to the CLIENT_ROLE_BROADCASTER. + m_rtcEngine->setClientRole(agora::rtc::CLIENT_ROLE_BROADCASTER); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("setClientRole broadcaster")); + + //start preview + CameraCapturerConfiguration config; + + m_rtcEngine->startPreview(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("start preview")); + + VideoCanvas canvas; + canvas.renderMode = media::base::RENDER_MODE_FIT; + canvas.uid = 0; + canvas.view = m_videoWnds[0].GetSafeHwnd(); + //setup local video in the engine to the canvas. + m_rtcEngine->setupLocalVideo(canvas); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("render local video")); + + return true; +} +//UnInitialize the Agora SDK +void CDlgBeauty2::UnInitAgora() +{ + if (m_rtcEngine) { + if (m_joinChannel) { + //leave channel primary camera + m_joinChannel = !m_rtcEngine->leaveChannel(); + m_lstInfo.InsertString(m_lstInfo.GetCount() - 1, _T("leaveChannel")); + //stop local video transcoder + m_rtcEngine->stopLocalVideoTranscoder(); + m_lstInfo.InsertString(m_lstInfo.GetCount() - 1, _T("stop local video transcoder")); + + //stop screen capture + m_rtcEngine->stopScreenCapture(); + m_lstInfo.InsertString(m_lstInfo.GetCount() - 1, _T("stop screen capture")); + + m_joinChannel = false; + m_btnJoinChannel.SetWindowText(commonCtrlJoinChannel); + } + + //stop preview in the engine. + m_rtcEngine->stopPreview(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("stopPreview")); + + //release engine. + if (m_initialize) { + m_rtcEngine->release(nullptr); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); + } + + m_rtcEngine = NULL; + } +} + + +//Initialize the Ctrl Text. +void CDlgBeauty2::InitCtrlText() +{ + m_cmbContrast.ResetContent(); + m_cmbContrast.InsertString(0, L"CONTRAST_LOW"); + m_cmbContrast.InsertString(1, L"CONTRAST_NORMAL"); + m_cmbContrast.InsertString(2, L"CONTRAST_HIGH"); + m_cmbContrast.SetCurSel(0); + m_staChannel.SetWindowText(commonCtrlChannel); + m_btnJoinChannel.SetWindowText(commonCtrlJoinChannel); +} + +void CDlgBeauty2::UpdateExtentCbState(bool isCheck) +{ + mCkExtention.SetCheck(isCheck); +} + +// resume window status. +void CDlgBeauty2::ResumeStatus() +{ + m_staVideoArea.ShowWindow(SW_SHOW); + RECT rcArea; + m_staVideoArea.GetClientRect(&rcArea); + + m_videoWnds[0].MoveWindow(&rcArea); + + m_videoWnds[0].ShowWindow(SW_SHOW); + m_videoWnds[1].ShowWindow(SW_HIDE); + + m_lstInfo.ResetContent(); + + m_btnJoinChannel.EnableWindow(TRUE); + m_edtChannel.SetWindowText(_T("")); + m_joinChannel = false; + m_initialize = false; + + m_sldLength.SetRange(0, 100); + m_sldLength.SetPos(50); + m_sldSkin.SetRange(0, 100); + m_sldSkin.SetPos(100); + + m_sdlLightening.SetRange(0, 100); + m_sdlLightening.SetPos(0); + m_sldRedness.SetRange(0, 100); + m_sldRedness.SetPos(0); + m_sldSmoothness.SetRange(0, 100); + m_sldSmoothness.SetPos(0); + + mSliderBright.SetRange(0, 100); + +} + + +LRESULT CDlgBeauty2::OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam) +{ + int cId = (int)wParam; + + CString strInfo; + strInfo.Format(_T("join channel success, uid=%u, cId=%d"), wParam, cId); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + return 0; +} + +//EID_LEAVE_CHANNEL message window handler. +LRESULT CDlgBeauty2::OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam) +{ + int cId = (int)wParam; + + m_btnJoinChannel.SetWindowText(commonCtrlJoinChannel); + CString strInfo; + strInfo.Format(_T("leave channel success")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + return 0; +} + +BOOL CDlgBeauty2::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + mBeautyDlgEx->Create(CDlgBeautyEx2::IDD); + mBeautyDlgEx->initData(&m_initialize, &m_rtcEngine, this); + mBeautyDlgEx->InitCtrlText(); + InitCtrlText(); + for (int i = 0; i < 2; ++i) { + m_videoWnds[i].Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 1, 1), &m_staVideoArea, i); + //set window background color. + m_videoWnds[i].SetFaceColor(RGB(0x58, 0x58, 0x58)); + } + CString strPath = GetExePath() + _T("\\agora.png"); + m_imgPath = cs2utf8(strPath); + ResumeStatus(); + + return TRUE; // return TRUE unless you set the focus to a control + +} + +void CDlgBeauty2::SetBeauty() +{ + if (!m_rtcEngine || !m_initialize) + return; + BeautyOptions option; + option.rednessLevel = m_sldRedness.GetPos() / 100.0f; + option.lighteningLevel = m_sdlLightening.GetPos() / 100.0f; + option.smoothnessLevel = m_sldSmoothness.GetPos() / 100.0f; + option.lighteningContrastLevel = (agora::rtc::BeautyOptions::LIGHTENING_CONTRAST_LEVEL)m_cmbContrast.GetCurSel(); + int ret = m_rtcEngine->setBeautyEffectOptions(m_chkBeauty.GetCheck() != 0, option); + if (ret < 0) { + CString strInfo; + strInfo.Format(_T("setBeautyEffectOptions: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + } + + FilterEffectOptions optionFilter; + optionFilter.path = "built_in_whiten_filter"; + optionFilter.strength = mSliderBright.GetPos() / 100.0f; + ret = m_rtcEngine->setFilterEffectOptions(m_chkBeauty.GetCheck() != 0, optionFilter); + if (ret < 0) { + CString strInfo; + strInfo.Format(_T("setFilterEffectOptions: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + } +} + +void CDlgBeauty2::SetColorful() +{ + if (!m_rtcEngine || !m_initialize) + return; + char szJson[512] = { 0 }; + agora::rtc::ColorEnhanceOptions options; + options.skinProtectLevel = m_sldSkin.GetPos() / 100.f; + options.strengthLevel = m_sldLength.GetPos() / 100.f; + sprintf_s(szJson, 512, "{\"enable\":%d, \"strength\":%f, \"skinProtect\": %f}", + m_chkEnhance.GetCheck() != 0, m_sldLength.GetPos() / 100.f, m_sldSkin.GetPos() / 100.f); + m_rtcEngine->setColorEnhanceOptions(m_chkEnhance.GetCheck() != 0, options); +} + +void CDlgBeauty2::OnBnClickedCheckBeautyEnable() +{ + SetBeauty(); +} + + +void CDlgBeauty2::OnNMCustomdrawSliderRedness(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + + *pResult = 0; + SetBeauty(); +} + + +void CDlgBeauty2::OnThumbposchangingSliderLightening(NMHDR* pNMHDR, LRESULT* pResult) +{ + NMTRBTHUMBPOSCHANGING* pNMTPC = reinterpret_cast(pNMHDR); + + *pResult = 0; + SetBeauty(); +} + + +void CDlgBeauty2::OnNMCustomdrawSliderSmoothness(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + SetBeauty(); + *pResult = 0; +} + + +void CDlgBeauty2::OnSelchangeComboBeauteLighteningContrastLevel() +{ + SetBeauty(); +} + + +void CDlgBeauty2::OnBnClickedCheckEnhance() +{ + SetColorful(); +} + + +void CDlgBeauty2::OnCustomdrawSliderStrength(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + SetColorful(); + *pResult = 0; +} + + +void CDlgBeauty2::OnCustomdrawSliderSkinProtect(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + SetColorful(); + *pResult = 0; +} + + +void CDlgBeauty2::OnBnClickedCheckVideoDenoise() +{ + char szJson[512] = { 0 }; + sprintf_s(szJson, 512, "{\"enable\":%d, \"mode\":%d, \"level\": %d}", + m_chkVideoDenoise.GetCheck() != 0, 1, 1); + VideoDenoiserOptions options; + options.level = VideoDenoiserOptions::VIDEO_DENOISER_LEVEL_FAST; + options.mode = VideoDenoiserOptions::VIDEO_DENOISER_MANUAL; + m_rtcEngine->setVideoDenoiserOptions(m_chkVideoDenoise.GetCheck() != 0, options); +} + + +void CDlgBeauty2::OnBnClickedCheckVideoDenoise2() +{ + agora::rtc::SegmentationProperty property; + agora::rtc::VirtualBackgroundSource background; + background.color = 0xFFFFFF; + background.blur_degree = VirtualBackgroundSource::BLUR_DEGREE_HIGH; + background.background_source_type = VirtualBackgroundSource::BACKGROUND_BLUR; + int ret = m_rtcEngine->enableVirtualBackground(m_chkVirtual.GetCheck() != 0, background, property, agora::media::PRIMARY_CAMERA_SOURCE); + CString strInfo; + strInfo.Format(_T("enableVirtualBackground: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_radioVirtualBgBlur.SetCheck(TRUE); + m_radioVirtualBgColor.SetCheck(FALSE); + m_radioVirtualBgImage.SetCheck(FALSE); + m_radioVirtualBgVideo.SetCheck(FALSE); + //m_rtcEngine->setExtensionProperty("video_segmentation_provider", "PortraitSegmentation", "configs", "{\"enable\":true,\"seg_params\":{\"matting_mode\":1},\"back_replace_params\":{\"type\":1,\"color\":16723281,\"source\":\"/sdcard/canoe_water_nature.jpg\", \"blur_degree\":2}}"); + // +} + +void CDlgBeauty2::OnBnClickedCheckLowlight() +{ + char szJson[512] = { 0 }; + sprintf_s(szJson, 512, "{\"enable\":%d, \"mode\":%d, \"level\": %d}", + m_chkLowlight.GetCheck() != 0, 1, 1); + LowlightEnhanceOptions options(LowlightEnhanceOptions::LOW_LIGHT_ENHANCE_MANUAL, LowlightEnhanceOptions::LOW_LIGHT_ENHANCE_LEVEL_FAST); + m_rtcEngine->setLowlightEnhanceOptions(m_chkLowlight.GetCheck() != 0, options); +} + + + + +void CDlgBeauty2::OnBnClickedStaticVirtualBgChoose(UINT idCtl) +{ + int isChecked = m_chkVirtual.GetCheck(); + if (isChecked && m_rtcEngine) { + VirtualBackgroundSource source; + + if (idCtl == IDC_RADIO_VIRTUAL_BG_BLUR) { + source.background_source_type = VirtualBackgroundSource::BACKGROUND_BLUR; + } + else if (idCtl == IDC_RADIO_VIRTUAL_BG_COLOR) { + source.background_source_type = VirtualBackgroundSource::BACKGROUND_COLOR; + source.color = 0x0000ff; + } + else if (idCtl == IDC_RADIO_VIRTUAL_BG_IMAGE) { + source.background_source_type = VirtualBackgroundSource::BACKGROUND_IMG; + source.source = m_imgPath.c_str(); + } + else if (idCtl == IDC_RADIO_VIRTUAL_BG_VIDEO) { + source.background_source_type = VirtualBackgroundSource::BACKGROUND_VIDEO; + source.source = "https://agora-adc-artifacts.s3.cn-north-1.amazonaws.com.cn/resources/sample.mp4"; + } + m_rtcEngine->enableVirtualBackground(true, source, SegmentationProperty(), PRIMARY_CAMERA_SOURCE); + } +} + + +void CDlgBeauty2::OnNMCustomdrawSliderBrihtness(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + SetBeauty(); + *pResult = 0; +} + + +void CDlgBeauty2::OnBnClickedCheckExtention() +{ + int checked = mCkExtention.GetCheck(); + if (checked) + { + mBeautyDlgEx->ShowWindow(SW_SHOW); + } + else { + mBeautyDlgEx->ShowWindow(SW_HIDE); + } +} diff --git a/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.h b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.h new file mode 100644 index 000000000..7fe874930 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeauty2.0.h @@ -0,0 +1,143 @@ +#pragma once +#pragma once + +#include +#include "AGVideoWnd.h" +#include "CDlgBeautyEx2.0.h" + +// CDlgBeauty + +class CBeautyEventHandler2 : public agora::rtc::IRtcEngineEventHandler +{ +public: + + //set the message notify window handler + void SetMsgReceiver(HWND hWnd) { m_hMsgHanlder = hWnd; } + + + std::string GetChannelName() { return m_strChannel; } + /* + note: + Join the channel callback.This callback method indicates that the client + successfully joined the specified channel.Channel ids are assigned based + on the channel name specified in the joinChannel. If IRtcEngine::joinChannel + is called without a user ID specified. The server will automatically assign one + parameters: + channel:channel name. + uid: user ID。If the UID is specified in the joinChannel, that ID is returned here; + Otherwise, use the ID automatically assigned by the Agora server. + elapsed: The Time from the joinChannel until this event occurred (ms). + */ + virtual void onJoinChannelSuccess(const char* channel, agora::rtc::uid_t uid, int elapsed) override { + if (m_hMsgHanlder) { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_JOINCHANNEL_SUCCESS), (WPARAM)uid, 0); + } + } + /* + note: + When the App calls the leaveChannel method, the SDK indicates that the App + has successfully left the channel. In this callback method, the App can get + the total call time, the data traffic sent and received by THE SDK and other + information. The App obtains the call duration and data statistics received + or sent by the SDK through this callback. + parameters: + stats: Call statistics. + */ + virtual void onLeaveChannel(const agora::rtc::RtcStats& stats) override { + if (m_hMsgHanlder) { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LEAVE_CHANNEL), 0, 0); + } + } +private: + HWND m_hMsgHanlder = NULL; + std::string m_strChannel = ""; + +}; +class CDlgBeauty2 : public CDialogEx +{ + DECLARE_DYNAMIC(CDlgBeauty2) + +public: + CDlgBeauty2(CWnd* pParent = nullptr); // + virtual ~CDlgBeauty2(); + + // + + enum { IDD = IDD_DIALOG_BEAUTY }; + + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV + + DECLARE_MESSAGE_MAP() +private: + void SetBeauty(); + void SetColorful(); + bool m_initialize = false; + bool m_joinChannel = false; + agora::rtc::IRtcEngine* m_rtcEngine = nullptr; + CBeautyEventHandler2 m_eventHandler; + CAGVideoWnd m_videoWnds[2]; + CDlgBeautyEx2* mBeautyDlgEx; +public: + afx_msg void OnBnClickedButtonJoinchannel(); + LRESULT OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam); + LRESULT OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam); + //Initialize the Agora SDK + bool InitAgora(); + //UnInitialize the Agora SDK + void UnInitAgora(); + // resume window status. + void ResumeStatus(); + //Initialize the Ctrl Text. + void InitCtrlText(); + + void UpdateExtentCbState(bool isCheck); + + CStatic m_staChannel; + CEdit m_edtChannel; + CButton m_btnJoinChannel; + CButton m_chkBeauty; + CStatic m_staContrast; + CStatic m_staRedness; + CStatic m_staSmoothness; + CStatic m_staLightening; + CButton m_chkEnhance; + CSliderCtrl m_sldLength; + CStatic m_staSkin; + CSliderCtrl m_sldSkin; + CButton m_chkVideoDenoise; + CButton m_chkVirtual; + CButton m_chkLowlight; + CSliderCtrl m_sdlLightening; + CSliderCtrl m_sldRedness; + CSliderCtrl m_sldSmoothness; + CListBox m_lstInfo; + CStatic m_staVideoArea; + CButton m_radioVirtualBgBlur; + CButton m_radioVirtualBgColor; + CButton m_radioVirtualBgImage; + CButton m_radioVirtualBgVideo; + std::string m_imgPath; + + virtual BOOL OnInitDialog(); + afx_msg void OnBnClickedCheckBeautyEnable(); + CComboBox m_cmbContrast; + afx_msg void OnNMCustomdrawSliderRedness(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnThumbposchangingSliderLightening(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderSmoothness(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnSelchangeComboBeauteLighteningContrastLevel(); + afx_msg void OnBnClickedCheckEnhance(); + afx_msg void OnCustomdrawSliderStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCustomdrawSliderSkinProtect(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnBnClickedCheckVideoDenoise(); + afx_msg void OnBnClickedCheckVideoDenoise2(); + afx_msg void OnBnClickedCheckLowlight(); + + afx_msg void OnBnClickedStaticVirtualBgChoose(UINT idCtl); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + CSliderCtrl mSliderBright; + afx_msg void OnNMCustomdrawSliderBrihtness(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnBnClickedCheckExtention(); + CButton mCkExtention; +}; diff --git a/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.cpp b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.cpp new file mode 100644 index 000000000..3fb1c2674 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.cpp @@ -0,0 +1,381 @@ +#include "stdafx.h" +#include "APIExample.h" +#include "CDlgBeautyEx2.0.h" +#include "CDlgBeauty2.0.h" + +IMPLEMENT_DYNAMIC(CDlgBeautyEx2, CDialogEx) + +CDlgBeautyEx2::CDlgBeautyEx2(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_DIALOG_BEAUTY_EX, pParent) +{ +} + +CDlgBeautyEx2::~CDlgBeautyEx2() +{ +} + +void CDlgBeautyEx2::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_CHECK_MAKE_UP, mCbMakeup); + DDX_Control(pDX, IDC_COMBO_BROW_STYLE, mDdBrowStyle); + DDX_Control(pDX, IDC_COMBO_BROW_COLOR, mDdBrowColor); + DDX_Control(pDX, IDC_SLIDER__BROW_STRENGTH, mSdBrowStrength); + DDX_Control(pDX, IDC_COMBO_LASH_STYLE, mDdLashStyle); + DDX_Control(pDX, IDC_COMBO_LASH_COLOR, mDdLashColor); + DDX_Control(pDX, IDC_SLIDER__LASH_STRENGTH, mSdLashStrength); + DDX_Control(pDX, IDC_COMBO_SHADOW_STYLE, mDdShadowStyle); + DDX_Control(pDX, IDC_SLIDER__SHADOW_STRENGTH, mSdShadowStrenght); + DDX_Control(pDX, IDC_COMBO_PUPIL_STYLE, mDdPupilStyle); + DDX_Control(pDX, IDC_SLIDER__Pupil_STRENGTH, mSdPupilStrength); + DDX_Control(pDX, IDC_COMBO_BLUSH_STYLE, mDdBlushStyle); + DDX_Control(pDX, IDC_COMBO_BLUSH_COLOR, mDdBlushColor); + DDX_Control(pDX, IDC_SLIDER__BLUSH_STRENGTH, mSdBlushStrength); + DDX_Control(pDX, IDC_COMBO_LIP_STYLE, mDdLipStyle); + DDX_Control(pDX, IDC_COMBO_LIP_COLOR, mDdLipColor); + DDX_Control(pDX, IDC_SLIDER__LIP_STRENGTH, mSdLipStrength); + DDX_Control(pDX, IDC_CHECK_BEAUTY_SHAPE, mCbBeautyShape); + DDX_Control(pDX, IDC_COMBO_FACE_SHAPE_AREA, mDdShapeArea); + DDX_Control(pDX, IDC_SLIDER__SHAPE_AREA_INTENSITY, mSdShapeAreaIntensity); + DDX_Control(pDX, IDC_COMBO_FACE_SHAPE_STYLE, mDdShapeStyle); + DDX_Control(pDX, IDC_SLIDER__SHAPE_STYLE_INTENSITY, mSdShapeStyleIntensity); +} + +BEGIN_MESSAGE_MAP(CDlgBeautyEx2, CDialogEx) + ON_WM_CLOSE() + ON_BN_CLICKED(IDC_CHECK_MAKE_UP, &CDlgBeautyEx2::OnBnClickedCheckMakeUp) + ON_CBN_SELCHANGE(IDC_COMBO_BROW_COLOR, &CDlgBeautyEx2::OnCbnSelchangeComboBrowColor) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__BROW_STRENGTH, &CDlgBeautyEx2::OnNMCustomdrawSliderBrowStrength) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__LASH_STRENGTH, &CDlgBeautyEx2::OnNMCustomdrawSliderLashStrength) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__SHADOW_STRENGTH, &CDlgBeautyEx2::OnNMCustomdrawSliderShadowStrength) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__Pupil_STRENGTH, &CDlgBeautyEx2::OnNMCustomdrawSliderPupilStrength) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__BLUSH_STRENGTH, &CDlgBeautyEx2::OnNMCustomdrawSliderBlushStrength) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__LIP_STRENGTH, &CDlgBeautyEx2::OnNMCustomdrawSliderLipStrength) + ON_CBN_SELCHANGE(IDC_COMBO_LASH_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboLashStyle) + ON_CBN_SELCHANGE(IDC_COMBO_LASH_COLOR, &CDlgBeautyEx2::OnCbnSelchangeComboLashColor) + ON_CBN_SELCHANGE(IDC_COMBO_SHADOW_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboShadowStyle) + ON_CBN_SELCHANGE(IDC_COMBO_PUPIL_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboPupilStyle) + ON_CBN_SELCHANGE(IDC_COMBO_BLUSH_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboBlushStyle) + ON_CBN_SELCHANGE(IDC_COMBO_BLUSH_COLOR, &CDlgBeautyEx2::OnCbnSelchangeComboBlushColor) + ON_CBN_SELCHANGE(IDC_COMBO_LIP_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboLipStyle) + ON_CBN_SELCHANGE(IDC_COMBO_LIP_COLOR, &CDlgBeautyEx2::OnCbnSelchangeComboLipColor) + ON_BN_CLICKED(IDC_CHECK_BEAUTY_SHAPE, &CDlgBeautyEx2::OnBnClickedCheckBeautyShape) + ON_CBN_SELCHANGE(IDC_COMBO_FACE_SHAPE_AREA, &CDlgBeautyEx2::OnCbnSelchangeComboFaceShapeArea) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__SHAPE_AREA_INTENSITY, &CDlgBeautyEx2::OnNMCustomdrawSliderShpaeAreaIntensity) + ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER__SHAPE_STYLE_INTENSITY, &CDlgBeautyEx2::OnNMCustomdrawSliderShpaeStyleIntensity) + ON_CBN_SELCHANGE(IDC_COMBO_FACE_SHAPE_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboFaceShapeStyle) + ON_CBN_SELCHANGE(IDC_COMBO_BROW_STYLE, &CDlgBeautyEx2::OnCbnSelchangeComboBrowStyle) +END_MESSAGE_MAP() + +void CDlgBeautyEx2::OnClose() +{ + if (m_beautyDlg) { + m_beautyDlg->UpdateExtentCbState(false); + } + CDialogEx::OnClose(); +} + +BOOL CDlgBeautyEx2::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + InitCtrlText(); + return TRUE; +} + + +void CDlgBeautyEx2::initData(bool* initialize, agora::rtc::IRtcEngine** engine, CDlgBeauty2* beautyDlg) +{ + m_initialize = initialize; + m_rtcEngine = engine; + m_beautyDlg = beautyDlg; +} + +void CDlgBeautyEx2::InitCtrlData() +{ + m_makeupOptions.reset(); + //make up + mCbMakeup.SetCheck(m_makeupOptions.enable_mu); + + mDdBrowStyle.SetCurSel(m_makeupOptions.browStyle); + mDdBrowColor.SetCurSel(m_makeupOptions.browColor); + mSdBrowStrength.SetRange(0, 100); + mSdBrowStrength.SetPos(m_makeupOptions.browStrength); + + mDdLashStyle.SetCurSel(m_makeupOptions.lashStyle); + mDdLashColor.SetCurSel(m_makeupOptions.lashColor); + mSdLashStrength.SetRange(0, 100); + mSdLashStrength.SetPos(m_makeupOptions.lashStrength); + + mDdShadowStyle.SetCurSel(m_makeupOptions.shadowStyle); + mSdShadowStrenght.SetRange(0, 100); + mSdShadowStrenght.SetPos(m_makeupOptions.shadowStrength); + + mDdPupilStyle.SetCurSel(m_makeupOptions.pupilStyle); + mSdPupilStrength.SetRange(0, 100); + mSdPupilStrength.SetPos(m_makeupOptions.pupilStrength); + + mDdBlushStyle.SetCurSel(m_makeupOptions.blushStyle); + mDdBlushColor.SetCurSel(m_makeupOptions.blushColor); + mSdBlushStrength.SetRange(0, 100); + mSdBlushStrength.SetPos(m_makeupOptions.blushStrength); + + mDdLipStyle.SetCurSel(m_makeupOptions.lipStyle); + mDdLipColor.SetCurSel(m_makeupOptions.lipColor); + mSdLipStrength.SetRange(0, 100); + mSdLipStrength.SetPos(m_makeupOptions.lipStrength); + + //beauty shape + mCbBeautyShape.SetCheck(0); + mDdShapeArea.SetCurSel(0); + mSdShapeAreaIntensity.SetRange(0, 100); + mSdShapeAreaIntensity.SetPos(0); + mDdShapeStyle.SetCurSel(0); + mSdShapeStyleIntensity.SetRange(0, 100); + mSdShapeStyleIntensity.SetPos(0); +} + +// set control text from config. +void CDlgBeautyEx2::InitCtrlText() +{ + //make up + mDdBrowStyle.ResetContent(); + mDdBrowStyle.InsertString(0, TEXT("CLOSE")); + mDdBrowStyle.InsertString(1, TEXT("TYPE1")); + mDdBrowStyle.InsertString(2, TEXT("TYPE2")); + mDdBrowColor.ResetContent(); + mDdBrowColor.InsertString(0, TEXT("NONE")); + mDdBrowColor.InsertString(1, TEXT("BLACK")); + mDdBrowColor.InsertString(2, TEXT("BROWN")); + + mDdLashStyle.ResetContent(); + mDdLashStyle.InsertString(0, TEXT("CLOSE")); + mDdLashStyle.InsertString(1, TEXT("TYPE1")); + mDdLashStyle.InsertString(2, TEXT("TYPE2")); + mDdLashColor.ResetContent(); + mDdLashColor.InsertString(0, TEXT("NONE")); + mDdLashColor.InsertString(1, TEXT("BLACK")); + mDdLashColor.InsertString(2, TEXT("BROWN")); + + mDdShadowStyle.ResetContent(); + mDdShadowStyle.InsertString(0, TEXT("CLOSE")); + mDdShadowStyle.InsertString(1, TEXT("TYPE1")); + mDdShadowStyle.InsertString(2, TEXT("TYPE2")); + + mDdPupilStyle.ResetContent(); + mDdPupilStyle.InsertString(0, TEXT("CLOSE")); + mDdPupilStyle.InsertString(1, TEXT("TYPE1")); + mDdPupilStyle.InsertString(2, TEXT("TYPE2")); + + mDdBlushStyle.ResetContent(); + mDdBlushStyle.InsertString(0, TEXT("CLOSE")); + mDdBlushStyle.InsertString(1, TEXT("TYPE1")); + mDdBlushStyle.InsertString(2, TEXT("TYPE2")); + mDdBlushColor.ResetContent(); + mDdBlushColor.InsertString(0, TEXT("NONE")); + mDdBlushColor.InsertString(1, TEXT("COLOR1")); + mDdBlushColor.InsertString(2, TEXT("COLOR2")); + mDdBlushColor.InsertString(3, TEXT("COLOR3")); + mDdBlushColor.InsertString(4, TEXT("COLOR4")); + mDdBlushColor.InsertString(5, TEXT("COLOR5")); + + mDdLipStyle.ResetContent(); + mDdLipStyle.InsertString(0, TEXT("CLOSE")); + mDdLipStyle.InsertString(1, TEXT("TYPE1")); + mDdLipStyle.InsertString(2, TEXT("TYPE2")); + mDdLipColor.ResetContent(); + mDdLipColor.InsertString(0, TEXT("NONE")); + mDdLipColor.InsertString(1, TEXT("COLOR1")); + mDdLipColor.InsertString(2, TEXT("COLOR2")); + mDdLipColor.InsertString(3, TEXT("COLOR3")); + mDdLipColor.InsertString(4, TEXT("COLOR4")); + mDdLipColor.InsertString(5, TEXT("COLOR5")); + + //beauty shape + mDdShapeArea.ResetContent(); + mDdShapeArea.InsertString(0, TEXT("FACE_SHAPE_AREA_NONE")); + mDdShapeArea.InsertString(1, TEXT("FACE_SHAPE_AREA_HEADSCALE")); + mDdShapeArea.InsertString(2, TEXT("FACE_SHAPE_AREA_FOREHEAD")); + mDdShapeArea.InsertString(3, TEXT("FACE_SHAPE_AREA_FACECONTOUR")); + mDdShapeArea.InsertString(4, TEXT("FACE_SHAPE_AREA_FACELENGTH")); + mDdShapeArea.InsertString(5, TEXT("FACE_SHAPE_AREA_FACEWIDTH")); + mDdShapeArea.InsertString(6, TEXT("FACE_SHAPE_AREA_CHEEKBONE")); + mDdShapeArea.InsertString(7, TEXT("FACE_SHAPE_AREA_CHEEK")); + mDdShapeArea.InsertString(8, TEXT("FACE_SHAPE_AREA_CHIN")); + mDdShapeArea.InsertString(9, TEXT("FACE_SHAPE_AREA_EYESCALE")); + mDdShapeArea.InsertString(10, TEXT("FACE_SHAPE_AREA_NOSELENGTH")); + mDdShapeArea.InsertString(11, TEXT("FACE_SHAPE_AREA_NOSEWIDTH")); + mDdShapeArea.InsertString(12, TEXT("FACE_SHAPE_AREA_MOUTHSCALE")); + + mDdShapeStyle.ResetContent(); + mDdShapeStyle.InsertString(0, TEXT("FACE_SHAPE_STYLE_FEMALE")); + mDdShapeStyle.InsertString(1, TEXT("FACE_SHAPE_STYLE_MALE")); + + InitCtrlData(); + +} + +void CDlgBeautyEx2::SetBeauty() +{ + if (*m_initialize && *m_rtcEngine) + { + std::string str = m_makeupOptions.toJsonString(); + (*m_rtcEngine)->setExtensionProperty("agora_video_filters_clear_vision", "clear_vision", "makeup_options", str.c_str(), PRIMARY_CAMERA_SOURCE); + bool flag = mCbBeautyShape.GetCheck() != 0; + (*m_rtcEngine)->setFaceShapeBeautyOptions(flag, m_faceShapeBeautyOptions); + (*m_rtcEngine)->setFaceShapeAreaOptions(m_faceShapeAreaOptions); + } +} + + + + +void CDlgBeautyEx2::OnBnClickedCheckMakeUp() +{ + m_makeupOptions.enable_mu = mCbMakeup.GetCheck(); + SetBeauty(); +} + +void CDlgBeautyEx2::OnCbnSelchangeComboBrowStyle() +{ + m_makeupOptions.browStyle = mDdBrowStyle.GetCurSel(); + SetBeauty(); +} + +void CDlgBeautyEx2::OnCbnSelchangeComboBrowColor() +{ + m_makeupOptions.browColor = mDdBrowColor.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnNMCustomdrawSliderBrowStrength(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_makeupOptions.browStrength = mSdBrowStrength.GetPos() / 100.0f; + SetBeauty(); + *pResult = 0; +} +void CDlgBeautyEx2::OnNMCustomdrawSliderLashStrength(NMHDR* pNMHDR, LRESULT* pResult) { + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_makeupOptions.lashStrength = mSdLashStrength.GetPos() / 100.0f; + SetBeauty(); + *pResult = 0; +} +void CDlgBeautyEx2::OnNMCustomdrawSliderShadowStrength(NMHDR* pNMHDR, LRESULT* pResult) { + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_makeupOptions.shadowStrength = mSdShadowStrenght.GetPos() / 100.0f; + SetBeauty(); + *pResult = 0; +} +void CDlgBeautyEx2::OnNMCustomdrawSliderPupilStrength(NMHDR* pNMHDR, LRESULT* pResult) { + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_makeupOptions.pupilStrength = mSdPupilStrength.GetPos() / 100.0f; + SetBeauty(); + *pResult = 0; +} +void CDlgBeautyEx2::OnNMCustomdrawSliderBlushStrength(NMHDR* pNMHDR, LRESULT* pResult) { + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_makeupOptions.blushStrength = mSdBlushStrength.GetPos() / 100.0f; + SetBeauty(); + *pResult = 0; +} +void CDlgBeautyEx2::OnNMCustomdrawSliderLipStrength(NMHDR* pNMHDR, LRESULT* pResult) { + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_makeupOptions.lipStrength = mSdLipStrength.GetPos() / 100.0f; + SetBeauty(); + *pResult = 0; +} + + + +void CDlgBeautyEx2::OnCbnSelchangeComboLashStyle() +{ + m_makeupOptions.lashStyle = mDdLashStyle.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboLashColor() +{ + m_makeupOptions.lashColor = mDdLashColor.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboShadowStyle() +{ + m_makeupOptions.shadowStyle = mDdShadowStyle.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboPupilStyle() +{ + m_makeupOptions.pupilStyle = mDdPupilStyle.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboBlushStyle() +{ + m_makeupOptions.blushStyle = mDdBlushStyle.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboBlushColor() +{ + m_makeupOptions.blushColor = mDdBlushColor.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboLipStyle() +{ + m_makeupOptions.lipStyle = mDdLipStyle.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboLipColor() +{ + m_makeupOptions.lipColor = mDdLipColor.GetCurSel(); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnBnClickedCheckBeautyShape() { + SetBeauty(); +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboFaceShapeArea() +{ + m_faceShapeAreaOptions.shapeArea = (FaceShapeAreaOptions::FACE_SHAPE_AREA)(mDdShapeArea.GetCurSel() - 1); + SetBeauty(); +} + + +void CDlgBeautyEx2::OnNMCustomdrawSliderShpaeAreaIntensity(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_faceShapeAreaOptions.shapeIntensity = mSdShapeAreaIntensity.GetPos(); + SetBeauty(); + *pResult = 0; +} + +void CDlgBeautyEx2::OnNMCustomdrawSliderShpaeStyleIntensity(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); + m_faceShapeBeautyOptions.styleIntensity = mSdShapeStyleIntensity.GetPos(); + SetBeauty(); + *pResult = 0; +} + + +void CDlgBeautyEx2::OnCbnSelchangeComboFaceShapeStyle() +{ + m_faceShapeBeautyOptions.shapeStyle = (FaceShapeBeautyOptions::FACE_SHAPE_BEAUTY_STYLE)mDdShapeStyle.GetCurSel(); + SetBeauty(); +} + diff --git a/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.h b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.h new file mode 100644 index 000000000..5252eb11e --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Beauty2.0/CDlgBeautyEx2.0.h @@ -0,0 +1,165 @@ +#pragma once +#pragma once +#include "AGVideoWnd.h" + +class CDlgBeauty2; + +struct MakeupOptions2 +{ + bool enable_mu; + + int browStyle; + int browColor; + float browStrength; + + int lashStyle; + int lashColor; + float lashStrength; + + int shadowStyle; + float shadowStrength; + + int pupilStyle; + float pupilStrength; + + int blushStyle; + int blushColor; + float blushStrength; + + int lipStyle; + int lipColor; + float lipStrength; + + void reset() + { + enable_mu = false; + + browStyle = 0; + browColor = 0; + browStrength = 0.0f; + + lashStyle = 0; + lashColor = 0; + lashStrength = 0.0f; + + shadowStyle = 0; + shadowStrength = 0.0f; + + pupilStyle = 0; + pupilStrength = 0.0f; + + blushStyle = 0; + blushColor = 0; + blushStrength = 0.0f; + + lipStyle = 0; + lipColor = 0; + lipStrength = 0.0f; + } + + MakeupOptions2() + { + reset(); + } + //to json string + std::string toJsonString() + { + std::string jsonStr = "{\"enable_mu\":"; + jsonStr += enable_mu ? "true" : "false"; + jsonStr += ",\"browStyle\":" + std::to_string(browStyle); + jsonStr += ",\"browColor\":" + std::to_string(browColor); + jsonStr += ",\"browStrength\":" + std::to_string(browStrength); + jsonStr += ",\"lashStyle\":" + std::to_string(lashStyle); + jsonStr += ",\"lashColor\":" + std::to_string(lashColor); + jsonStr += ",\"lashStrength\":" + std::to_string(lashStrength); + jsonStr += ",\"shadowStyle\":" + std::to_string(shadowStyle); + jsonStr += ",\"shadowStrength\":" + std::to_string(shadowStrength); + jsonStr += ",\"pupilStyle\":" + std::to_string(pupilStyle); + jsonStr += ",\"pupilStrength\":" + std::to_string(pupilStrength); + jsonStr += ",\"blushStyle\":" + std::to_string(blushStyle); + jsonStr += ",\"blushColor\":" + std::to_string(blushColor); + jsonStr += ",\"blushStrength\":" + std::to_string(blushStrength); + jsonStr += ",\"lipStyle\":" + std::to_string(lipStyle); + jsonStr += ",\"lipColor\":" + std::to_string(lipColor); + jsonStr += ",\"lipStrength\":" + std::to_string(lipStrength); + jsonStr += "}"; + return jsonStr; + } + +}; + +class CDlgBeautyEx2 : public CDialogEx +{ + DECLARE_DYNAMIC(CDlgBeautyEx2) + +public: + CDlgBeautyEx2(CWnd* pParent = nullptr); // standard constructor + virtual ~CDlgBeautyEx2(); + enum + { + IDD = IDD_DIALOG_BEAUTY_EX + }; +private: + bool* m_initialize = nullptr; + agora::rtc::IRtcEngine** m_rtcEngine = nullptr; + CDlgBeauty2* m_beautyDlg = nullptr; + MakeupOptions2 m_makeupOptions; + FaceShapeAreaOptions m_faceShapeAreaOptions; + FaceShapeBeautyOptions m_faceShapeBeautyOptions; +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + afx_msg void OnClose(); + DECLARE_MESSAGE_MAP() + +public: + void initData(bool* initialize, agora::rtc::IRtcEngine** engine, CDlgBeauty2* beautyDlg); + void InitCtrlText(); + void InitCtrlData(); + void SetBeauty(); + + CButton mCbMakeup; + CComboBox mDdBrowColor; + CComboBox mDdBrowStyle; + CSliderCtrl mSdBrowStrength; + CComboBox mDdLashStyle; + CComboBox mDdLashColor; + CSliderCtrl mSdLashStrength; + CComboBox mDdShadowStyle; + CSliderCtrl mSdShadowStrenght; + CComboBox mDdPupilStyle; + CSliderCtrl mSdPupilStrength; + CComboBox mDdBlushStyle; + CComboBox mDdBlushColor; + CSliderCtrl mSdBlushStrength; + CComboBox mDdLipStyle; + CComboBox mDdLipColor; + CSliderCtrl mSdLipStrength; + CButton mCbBeautyShape; + CComboBox mDdShapeArea; + CSliderCtrl mSdShapeAreaIntensity; + CComboBox mDdShapeStyle; + CSliderCtrl mSdShapeStyleIntensity; + afx_msg void OnBnClickedCheckMakeUp(); + afx_msg void OnCbnSelchangeComboBrowColor(); + afx_msg void OnNMCustomdrawSliderBrowStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderLashStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderShadowStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderPupilStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderBlushStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderLipStrength(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCbnSelchangeComboLashStyle(); + afx_msg void OnCbnSelchangeComboLashColor(); + afx_msg void OnCbnSelchangeComboShadowStyle(); + afx_msg void OnCbnSelchangeComboPupilStyle(); + afx_msg void OnCbnSelchangeComboBlushStyle(); + afx_msg void OnCbnSelchangeComboBlushColor(); + afx_msg void OnCbnSelchangeComboLipStyle(); + afx_msg void OnCbnSelchangeComboLipColor(); + afx_msg void OnBnClickedCheckBeautyShape(); + afx_msg void OnCbnSelchangeComboFaceShapeArea(); + afx_msg void OnNMCustomdrawSliderShpaeAreaIntensity(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnNMCustomdrawSliderShpaeStyleIntensity(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCbnSelchangeComboFaceShapeStyle(); + afx_msg void OnCbnSelchangeComboBrowStyle(); +}; diff --git a/windows/APIExample/APIExample/Advanced/BeautyAudio/CAgoraBeautyAudio.cpp b/windows/APIExample/APIExample/Advanced/BeautyAudio/CAgoraBeautyAudio.cpp index 08159d516..8319d5342 100644 --- a/windows/APIExample/APIExample/Advanced/BeautyAudio/CAgoraBeautyAudio.cpp +++ b/windows/APIExample/APIExample/Advanced/BeautyAudio/CAgoraBeautyAudio.cpp @@ -91,7 +91,7 @@ void CAgoraBeautyAudio::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/CrossChannel/CAgoraCrossChannelDlg.cpp b/windows/APIExample/APIExample/Advanced/CrossChannel/CAgoraCrossChannelDlg.cpp index d5aaa5884..052db959e 100644 --- a/windows/APIExample/APIExample/Advanced/CrossChannel/CAgoraCrossChannelDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/CrossChannel/CAgoraCrossChannelDlg.cpp @@ -134,7 +134,7 @@ void CAgoraCrossChannelDlg::UnInitAgora() m_rtcEngine->disableVideo(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; if(m_srcInfo->channelName) diff --git a/windows/APIExample/APIExample/Advanced/CustomAudioCapture/CAgoraCaptureAudioDlg.cpp b/windows/APIExample/APIExample/Advanced/CustomAudioCapture/CAgoraCaptureAudioDlg.cpp index f76bfe46a..9c07e6d19 100644 --- a/windows/APIExample/APIExample/Advanced/CustomAudioCapture/CAgoraCaptureAudioDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/CustomAudioCapture/CAgoraCaptureAudioDlg.cpp @@ -173,7 +173,7 @@ void CAgoraCaptureAduioDlg::UnInitAgora() m_agAudioCaptureDevice.engine_ = NULL; //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/CustomEncrypt/CAgoraCustomEncryptDlg.cpp b/windows/APIExample/APIExample/Advanced/CustomEncrypt/CAgoraCustomEncryptDlg.cpp index 26acb77bc..914e38907 100755 --- a/windows/APIExample/APIExample/Advanced/CustomEncrypt/CAgoraCustomEncryptDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/CustomEncrypt/CAgoraCustomEncryptDlg.cpp @@ -110,7 +110,7 @@ void CAgoraCustomEncryptDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/CustomVideoCapture/CAgoraCaptureVideoDlg.cpp b/windows/APIExample/APIExample/Advanced/CustomVideoCapture/CAgoraCaptureVideoDlg.cpp index d4404c436..bda9fb0f6 100755 --- a/windows/APIExample/APIExample/Advanced/CustomVideoCapture/CAgoraCaptureVideoDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/CustomVideoCapture/CAgoraCaptureVideoDlg.cpp @@ -133,7 +133,7 @@ void CAgoraCaptureVideoDlg::UnInitAgora() m_rtcEngine->disableVideo(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; } diff --git a/windows/APIExample/APIExample/Advanced/FaceCapture/CAgoraFaceCaptureDlg.cpp b/windows/APIExample/APIExample/Advanced/FaceCapture/CAgoraFaceCaptureDlg.cpp index 468630fa4..46a4f5edd 100644 --- a/windows/APIExample/APIExample/Advanced/FaceCapture/CAgoraFaceCaptureDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/FaceCapture/CAgoraFaceCaptureDlg.cpp @@ -134,7 +134,7 @@ void CAgoraFaceCaptureDlg::UnInitAgora() m_faceInfoObserver.SetMsgReceiver(nullptr); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/LocalVideoTranscoding/CLocalVideoTranscodingDlg.cpp b/windows/APIExample/APIExample/Advanced/LocalVideoTranscoding/CLocalVideoTranscodingDlg.cpp index 068aac922..e6612339d 100755 --- a/windows/APIExample/APIExample/Advanced/LocalVideoTranscoding/CLocalVideoTranscodingDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/LocalVideoTranscoding/CLocalVideoTranscodingDlg.cpp @@ -329,7 +329,7 @@ void CLocalVideoTranscodingDlg::UnInitAgora() //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/MediaEncrypt/CAgoraMediaEncryptDlg.cpp b/windows/APIExample/APIExample/Advanced/MediaEncrypt/CAgoraMediaEncryptDlg.cpp index b59f1b842..0347c346c 100755 --- a/windows/APIExample/APIExample/Advanced/MediaEncrypt/CAgoraMediaEncryptDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/MediaEncrypt/CAgoraMediaEncryptDlg.cpp @@ -112,7 +112,7 @@ void CAgoraMediaEncryptDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/MediaPlayer/CAgoraMediaPlayer.cpp b/windows/APIExample/APIExample/Advanced/MediaPlayer/CAgoraMediaPlayer.cpp index 952e71632..3ed80f9c1 100755 --- a/windows/APIExample/APIExample/Advanced/MediaPlayer/CAgoraMediaPlayer.cpp +++ b/windows/APIExample/APIExample/Advanced/MediaPlayer/CAgoraMediaPlayer.cpp @@ -145,7 +145,7 @@ void CAgoraMediaPlayer::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/MediaRecorder/CAgoraMediaRecorder.cpp b/windows/APIExample/APIExample/Advanced/MediaRecorder/CAgoraMediaRecorder.cpp index 8845174c0..8d65e1adc 100755 --- a/windows/APIExample/APIExample/Advanced/MediaRecorder/CAgoraMediaRecorder.cpp +++ b/windows/APIExample/APIExample/Advanced/MediaRecorder/CAgoraMediaRecorder.cpp @@ -135,7 +135,7 @@ void CAgoraMediaRecorder::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/Metadata/CAgoraMetaDataDlg.cpp b/windows/APIExample/APIExample/Advanced/Metadata/CAgoraMetaDataDlg.cpp index 4807f2ac4..38275ed6d 100644 --- a/windows/APIExample/APIExample/Advanced/Metadata/CAgoraMetaDataDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/Metadata/CAgoraMetaDataDlg.cpp @@ -79,7 +79,7 @@ void CAgoraMetaDataObserver::SetSendSEI(std::string utf8Msg) is called without a user ID specified. The server will automatically assign one parameters: channel:channel name. - uid: user ID。If the UID is specified in the joinChannel, that ID is returned here; + uid: user ID锟斤拷If the UID is specified in the joinChannel, that ID is returned here; Otherwise, use the ID automatically assigned by the Agora server. elapsed: The Time from the joinChannel until this event occurred (ms). */ @@ -100,7 +100,7 @@ void CAgoraMetaDataEventHanlder::onJoinChannelSuccess(const char* channel, uid_t parameters: uid: remote user/anchor ID for newly added channel. elapsed: The joinChannel is called from the local user to the delay triggered - by the callback(ms). + by the callback锟斤拷ms). */ void CAgoraMetaDataEventHanlder::onUserJoined(uid_t uid, int elapsed) { if (m_hMsgHanlder) { @@ -355,7 +355,7 @@ void CAgoraMetaDataDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/MultiCamera/CMultiCameraDlg.cpp b/windows/APIExample/APIExample/Advanced/MultiCamera/CMultiCameraDlg.cpp index 7e6ffd835..0f8e30454 100644 --- a/windows/APIExample/APIExample/Advanced/MultiCamera/CMultiCameraDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/MultiCamera/CMultiCameraDlg.cpp @@ -357,7 +357,7 @@ void CMultiCameraDlg::UnInitAgora() //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; } diff --git a/windows/APIExample/APIExample/Advanced/MultiChannel/CAgoraMultiChannelDlg.cpp b/windows/APIExample/APIExample/Advanced/MultiChannel/CAgoraMultiChannelDlg.cpp index bc7452bfa..b3338601f 100755 --- a/windows/APIExample/APIExample/Advanced/MultiChannel/CAgoraMultiChannelDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/MultiChannel/CAgoraMultiChannelDlg.cpp @@ -133,7 +133,7 @@ void CAgoraMultiChannelDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/MultiVideoSource/CAgoraMutilVideoSourceDlg.cpp b/windows/APIExample/APIExample/Advanced/MultiVideoSource/CAgoraMutilVideoSourceDlg.cpp index 64856b9e8..cdc1faadf 100755 --- a/windows/APIExample/APIExample/Advanced/MultiVideoSource/CAgoraMutilVideoSourceDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/MultiVideoSource/CAgoraMutilVideoSourceDlg.cpp @@ -371,7 +371,7 @@ void CAgoraMutilVideoSourceDlg::UnInitAgora() m_rtcEngine->stopPreview(); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/MultiVideoSourceTracks/MultiVideoSourceTracks.cpp b/windows/APIExample/APIExample/Advanced/MultiVideoSourceTracks/MultiVideoSourceTracks.cpp index 45928632c..23f89e186 100755 --- a/windows/APIExample/APIExample/Advanced/MultiVideoSourceTracks/MultiVideoSourceTracks.cpp +++ b/windows/APIExample/APIExample/Advanced/MultiVideoSourceTracks/MultiVideoSourceTracks.cpp @@ -326,7 +326,7 @@ void MultiVideoSourceTracks::UnInitAgora() m_rtcEngine->stopPreview(); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; @@ -515,7 +515,7 @@ LRESULT MultiVideoSourceTracks::OnEIDRemoteAudioStats(WPARAM wParam, LPARAM lPar is called without a user ID specified. The server will automatically assign one parameters: channel:channel name. - uid: user ID。If the UID is specified in the joinChannel, that ID is returned here; + uid: user ID锟斤拷If the UID is specified in the joinChannel, that ID is returned here; Otherwise, use the ID automatically assigned by the Agora server. elapsed: The Time from the joinChannel until this event occurred (ms). */ diff --git a/windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.cpp b/windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.cpp new file mode 100644 index 000000000..117f5f726 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.cpp @@ -0,0 +1,537 @@ +// CMultipathDlg.cpp : implementation file + +#include "stdafx.h" +#include "APIExample.h" +#include "CMultipathDlg.h" + +void CMultipathRtcEngineEventHandler::onJoinChannelSuccess(const char *channel, uid_t uid, int elapsed) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_JOINCHANNEL_SUCCESS), (WPARAM)uid, (LPARAM)elapsed); + } +} + +void CMultipathRtcEngineEventHandler::onUserJoined(uid_t uid, int elapsed) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_USER_JOINED), (WPARAM)uid, (LPARAM)elapsed); + } +} + +void CMultipathRtcEngineEventHandler::onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_USER_OFFLINE), (WPARAM)uid, (LPARAM)reason); + } +} + +void CMultipathRtcEngineEventHandler::onLeaveChannel(const RtcStats &stats) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LEAVE_CHANNEL), 0, 0); + } +} + +void CMultipathRtcEngineEventHandler::onMultipathStats(const MultipathStats& stats) +{ + if (m_hMsgHanlder) + { + MultipathStats* statsPtr = new MultipathStats(stats); + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_MULTIPATH_STATS), (WPARAM)statsPtr, 0); + } +} + +void CMultipathRtcEngineEventHandler::onNetworkTypeChanged(NETWORK_TYPE type) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_NETWORK_TYPE_CHANGED), (WPARAM)type, 0); + } +} + +// CMultipathDlg dialog +IMPLEMENT_DYNAMIC(CMultipathDlg, CDialogEx) + +CMultipathDlg::CMultipathDlg(CWnd *pParent /*=nullptr*/) + : CDialogEx(IDD_DIALOG_MULTIPATH, pParent) +{ +} + +CMultipathDlg::~CMultipathDlg() +{ +} + +void CMultipathDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_COMBO_ROLE, m_cmbRole); + DDX_Control(pDX, IDC_STATIC_ROLE, m_staRole); + DDX_Control(pDX, IDC_EDIT_CHANNELNAME, m_edtChannelName); + DDX_Control(pDX, IDC_BUTTON_JOINCHANNEL, m_btnJoinChannel); + DDX_Control(pDX, IDC_LIST_INFO_MULTIPATH, m_lstInfo); + DDX_Control(pDX, IDC_STATIC_VIDEO, m_videoArea); + DDX_Control(pDX, IDC_STATIC_CHANNELNAME, m_staChannelName); + DDX_Control(pDX, IDC_COMBO_MULTIPATH_MODE, m_cmbMultipathMode); + DDX_Control(pDX, IDC_STATIC_MULTIPATH_MODE, m_staMultipathMode); + DDX_Control(pDX, IDC_CHECK_ENABLE_MULTIPATH, m_chkEnableMultipath); + DDX_Control(pDX, IDC_STATIC_ENABLE_MULTIPATH, m_staEnableMultipath); +} + +BEGIN_MESSAGE_MAP(CMultipathDlg, CDialogEx) +ON_BN_CLICKED(IDC_BUTTON_JOINCHANNEL, &CMultipathDlg::OnBnClickedButtonJoinchannel) +ON_CBN_SELCHANGE(IDC_COMBO_ROLE, &CMultipathDlg::OnSelchangeComboRole) +ON_CBN_SELCHANGE(IDC_COMBO_MULTIPATH_MODE, &CMultipathDlg::OnSelchangeComboMultipathMode) +ON_BN_CLICKED(IDC_CHECK_ENABLE_MULTIPATH, &CMultipathDlg::OnBnClickedCheckEnableMultipath) +ON_MESSAGE(WM_MSGID(EID_JOINCHANNEL_SUCCESS), &CMultipathDlg::OnEIDJoinChannelSuccess) +ON_MESSAGE(WM_MSGID(EID_LEAVE_CHANNEL), &CMultipathDlg::OnEIDLeaveChannel) +ON_MESSAGE(WM_MSGID(EID_USER_JOINED), &CMultipathDlg::OnEIDUserJoined) +ON_MESSAGE(WM_MSGID(EID_USER_OFFLINE), &CMultipathDlg::OnEIDUserOffline) +ON_MESSAGE(WM_MSGID(EID_MULTIPATH_STATS), &CMultipathDlg::OnEIDMultipathStats) +ON_MESSAGE(WM_MSGID(EID_NETWORK_TYPE_CHANGED), &CMultipathDlg::OnEIDNetworkTypeChanged) +ON_WM_SHOWWINDOW() +END_MESSAGE_MAP() + +// CMultipathDlg message handlers +BOOL CMultipathDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + CreateAllVideoWnds(); + + // Initialize role combo box + m_cmbRole.InsertString(0, _T("Broadcaster")); + m_cmbRole.InsertString(1, _T("Audience")); + m_cmbRole.SetCurSel(0); + + // Initialize multipath mode combo box + m_cmbMultipathMode.InsertString(0, _T("Duplicate")); + m_cmbMultipathMode.InsertString(1, _T("Dynamic")); + m_cmbMultipathMode.SetCurSel(0); + + // Initialize multipath related controls + m_staEnableMultipath.SetWindowText(_T("Enable Multipath:")); + m_chkEnableMultipath.SetCheck(BST_UNCHECKED); + + InitCtrlText(); + InitAgora(); + + return TRUE; +} + +void CMultipathDlg::InitCtrlText() +{ + m_staRole.SetWindowText(_T("Role:")); + m_staChannelName.SetWindowText(_T("Channel:")); + m_btnJoinChannel.SetWindowText(_T("Join Channel")); + m_staMultipathMode.SetWindowText(_T("Multipath Mode:")); +} + +void CMultipathDlg::CreateAllVideoWnds() +{ + for (int i = 0; i < VIDEO_COUNT_MULTIPATH; i++) + { + m_videoWnds[i].Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 1, 1), this, IDC_BASEWND_VIDEO_MULTIPATH + i); + m_videoWnds[i].SetUID(0); + } + + // Position video windows + RECT rcArea; + m_videoArea.GetClientRect(&rcArea); + int w = (rcArea.right - rcArea.left - 5) / 2; + int h = rcArea.bottom - rcArea.top - 10; + + m_videoWnds[0].MoveWindow(5, 5, w, h, TRUE); + m_videoWnds[1].MoveWindow(w + 10, 5, w, h, TRUE); + + for (int i = 0; i < VIDEO_COUNT_MULTIPATH; i++) + { + m_videoWnds[i].SetParent(&m_videoArea); + m_videoWnds[i].ShowWindow(SW_SHOW); + } +} + +bool CMultipathDlg::InitAgora() +{ + // create Agora RTC engine + m_rtcEngine = createAgoraRtcEngine(); + if (!m_rtcEngine) + { + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("createAgoraRtcEngine failed")); + return false; + } + + // set message notify receiver window + m_eventHandler.SetMsgReceiver(m_hWnd); + + RtcEngineContext context; + std::string strAppID = GET_APP_ID; + context.appId = strAppID.c_str(); + context.eventHandler = &m_eventHandler; + context.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING; + + // initialize the Agora RTC engine context. + int ret = m_rtcEngine->initialize(context); + if (ret != 0) + { + m_initialize = false; + CString strInfo; + strInfo.Format(_T("initialize failed: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + return false; + } + else + m_initialize = true; + + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("initialize success")); + + // enable video and audio + m_rtcEngine->enableVideo(); + m_rtcEngine->enableAudio(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("enable video and audio")); + + return true; +} + +void CMultipathDlg::UnInitAgora() +{ + if (m_rtcEngine) + { + if (m_joinChannel) + m_rtcEngine->leaveChannel(); + m_rtcEngine->release(nullptr); + m_rtcEngine = nullptr; + } +} + +void CMultipathDlg::ResumeStatus() +{ + m_lstInfo.ResetContent(); + m_lstUids.clear(); + m_joinChannel = false; + m_btnJoinChannel.SetWindowText(_T("Join Channel")); + m_btnJoinChannel.EnableWindow(TRUE); +} + +void CMultipathDlg::RenderLocalVideo() +{ + if (m_rtcEngine) + { + m_rtcEngine->enableLocalVideo(true); + m_rtcEngine->startPreview(); + VideoCanvas canvas; + canvas.renderMode = media::base::RENDER_MODE_HIDDEN; + canvas.uid = 0; + canvas.view = m_videoWnds[0].GetSafeHwnd(); + m_rtcEngine->setupLocalVideo(canvas); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("render local video")); + } +} + +void CMultipathDlg::StopLocalVideo() +{ + if (m_rtcEngine) + { + m_rtcEngine->enableLocalVideo(false); + m_rtcEngine->stopPreview(); + } +} + +void CMultipathDlg::ResetVideoView() +{ + VideoCanvas canvas; + canvas.uid = 0; + canvas.renderMode = media::base::RENDER_MODE_HIDDEN; + m_rtcEngine->setupLocalVideo(canvas); + canvas.view = m_videoWnds[0].GetSafeHwnd(); + m_rtcEngine->setupLocalVideo(canvas); + + if (m_videoWnds[1].GetUID() != 0) + { + VideoCanvas remoteCanvas; + remoteCanvas.uid = m_videoWnds[1].GetUID(); + remoteCanvas.renderMode = media::base::RENDER_MODE_HIDDEN; + m_rtcEngine->setupRemoteVideo(remoteCanvas); + remoteCanvas.view = m_videoWnds[1].GetSafeHwnd(); + m_rtcEngine->setupRemoteVideo(remoteCanvas); + } +} + +void CMultipathDlg::OnBnClickedButtonJoinchannel() +{ + if (!m_rtcEngine || !m_initialize) + return; + + if (!m_joinChannel) + { + CString strChannelName; + m_edtChannelName.GetWindowText(strChannelName); + if (strChannelName.IsEmpty()) + { + AfxMessageBox(_T("Fill channel name first")); + return; + } + + // Set client role + CLIENT_ROLE_TYPE role = m_cmbRole.GetCurSel() == 0 ? CLIENT_ROLE_BROADCASTER : CLIENT_ROLE_AUDIENCE; + m_rtcEngine->setClientRole(role); + + // Configure ChannelMediaOptions + ChannelMediaOptions options; + options.autoSubscribeAudio = true; + options.autoSubscribeVideo = true; + options.publishMicrophoneTrack = (role == CLIENT_ROLE_BROADCASTER); + options.publishCameraTrack = (role == CLIENT_ROLE_BROADCASTER); + + // Multipath configuration + options.enableMultipath = (m_chkEnableMultipath.GetCheck() == BST_CHECKED); + + // Get multipath mode + int modeIndex = m_cmbMultipathMode.GetCurSel(); + MultipathMode mode = (modeIndex == 0) ? Duplicate : Dynamic; + options.uplinkMultipathMode = mode; + options.downlinkMultipathMode = mode; + + // Set preferred path type + options.preferMultipathType = WIFI; + + // Join channel + std::string stdStrChannelName = cs2utf8(strChannelName); + int ret = m_rtcEngine->joinChannel(NULL, stdStrChannelName.c_str(), 0, options); + if (ret == 0) + { + m_btnJoinChannel.EnableWindow(FALSE); + } + } + else + { + m_rtcEngine->leaveChannel(); + } +} + +void CMultipathDlg::OnSelchangeComboRole() +{ + if (m_rtcEngine && m_initialize) + { + CLIENT_ROLE_TYPE role = m_cmbRole.GetCurSel() == 0 ? CLIENT_ROLE_BROADCASTER : CLIENT_ROLE_AUDIENCE; + m_rtcEngine->setClientRole(role); + } +} + +void CMultipathDlg::OnSelchangeComboMultipathMode() +{ + int select_mode = m_cmbMultipathMode.GetCurSel(); + m_multipathModeStr = (select_mode == 0) ? "Duplicate" : "Dynamic"; + + if (m_rtcEngine && m_initialize && m_joinChannel) + { + ChannelMediaOptions options; + MultipathMode mode = (select_mode == 0) ? Duplicate : Dynamic; + options.uplinkMultipathMode = mode; + options.downlinkMultipathMode = mode; + + int ret = m_rtcEngine->updateChannelMediaOptions(options); + + CString strInfo; + strInfo.Format(_T("Multipath mode changed to: %s, result: %d"), + CString(m_multipathModeStr.c_str()), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + } + else + { + CString strInfo; + strInfo.Format(_T("Multipath mode changed to: %s"), select_mode == 0 ? _T("Duplicate") : _T("Dynamic")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + } +} + +void CMultipathDlg::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialogEx::OnShowWindow(bShow, nStatus); + if (bShow) // bShow is true, show window + { + InitAgora(); + RenderLocalVideo(); + } + else { + ResumeStatus(); + } +} + +LRESULT CMultipathDlg::OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam) +{ + m_btnJoinChannel.EnableWindow(TRUE); + m_joinChannel = true; + m_btnJoinChannel.SetWindowText(_T("Leave Channel")); + + // Disable multipath mode combo box when in channel + m_cmbMultipathMode.EnableWindow(FALSE); + + CString strInfo; + strInfo.Format(_T("join channel success, uid=%u"), wParam); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + //notify parent window + ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(EID_JOINCHANNEL_SUCCESS), TRUE, 0); + + return 0; +} + +LRESULT CMultipathDlg::OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam) +{ + m_btnJoinChannel.EnableWindow(TRUE); + m_joinChannel = false; + m_btnJoinChannel.SetWindowText(_T("Join Channel")); + + // Re-enable multipath mode combo box when leaving channel + m_cmbMultipathMode.EnableWindow(TRUE); + + CString strInfo; + strInfo.Format(_T("leave channel success")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstUids.clear(); + m_videoWnds[1].SetUID(0); + + //notify parent window + ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(EID_JOINCHANNEL_SUCCESS), FALSE, 0); + + return 0; +} + +LRESULT CMultipathDlg::OnEIDUserJoined(WPARAM wParam, LPARAM lParam) +{ + CString strInfo; + strInfo.Format(_T("%u joined"), wParam); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + + m_lstUids.push_back(wParam); + if (m_videoWnds[1].GetUID() == 0) + { + VideoCanvas canvas; + canvas.uid = wParam; + canvas.view = m_videoWnds[1].GetSafeHwnd(); + canvas.renderMode = media::base::RENDER_MODE_HIDDEN; + m_rtcEngine->setupRemoteVideo(canvas); + m_videoWnds[1].SetUID(wParam); + } + + return 0; +} + +LRESULT CMultipathDlg::OnEIDUserOffline(WPARAM wParam, LPARAM lParam) +{ + uid_t remoteUid = (uid_t)wParam; + VideoCanvas canvas; + canvas.uid = remoteUid; + canvas.view = NULL; + m_rtcEngine->setupRemoteVideo(canvas); + + CString strInfo; + strInfo.Format(_T("%u offline, reason:%d"), remoteUid, lParam); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + + if (m_videoWnds[1].GetUID() == remoteUid) + { + m_videoWnds[1].SetUID(0); + m_videoWnds[1].Invalidate(); + } + + m_lstUids.remove(remoteUid); + return 0; +} + +LRESULT CMultipathDlg::OnEIDMultipathStats(WPARAM wParam, LPARAM lParam) +{ + MultipathStats* stats = (MultipathStats*)wParam; + if (stats) + { + m_activePathNum = stats->activePathNum; + + CString strInfo; + strInfo.Format(_T("Multipath Stats - Active Paths: %d"), m_activePathNum); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + + delete stats; + } + return 0; +} + +LRESULT CMultipathDlg::OnEIDNetworkTypeChanged(WPARAM wParam, LPARAM lParam) +{ + int type = (int)wParam; + + switch (type) + { + case NETWORK_TYPE_DISCONNECTED: + m_networkStr = "disconnected"; + break; + case NETWORK_TYPE_LAN: + m_networkStr = "lan"; + break; + case NETWORK_TYPE_WIFI: + m_networkStr = "wifi"; + break; + case NETWORK_TYPE_MOBILE_2G: + case NETWORK_TYPE_MOBILE_3G: + case NETWORK_TYPE_MOBILE_4G: + case NETWORK_TYPE_MOBILE_5G: + m_networkStr = "mobile"; + break; + default: + m_networkStr = "unknown"; + break; + } + + CString strInfo; + strInfo.Format(_T("Network Type Changed: %s"), CString(m_networkStr.c_str())); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + + return 0; +} + +void CMultipathDlg::OnBnClickedCheckEnableMultipath() +{ + BOOL bChecked = m_chkEnableMultipath.GetCheck(); + + CString strInfo; + strInfo.Format(_T("Multipath %s"), bChecked ? _T("enabled") : _T("disabled")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + + // If already in channel, update the channel media options + if (m_rtcEngine && m_initialize && m_joinChannel) + { + ChannelMediaOptions options; + options.enableMultipath = (bChecked == BST_CHECKED); + + // Get current multipath mode + int modeIndex = m_cmbMultipathMode.GetCurSel(); + MultipathMode mode = (modeIndex == 0) ? Duplicate : Dynamic; + options.uplinkMultipathMode = mode; + options.downlinkMultipathMode = mode; + options.preferMultipathType = WIFI; + + int ret = m_rtcEngine->updateChannelMediaOptions(options); + + CString strUpdateInfo; + strUpdateInfo.Format(_T("Update multipath settings, result: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strUpdateInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + } +} + +BOOL CMultipathDlg::PreTranslateMessage(MSG* pMsg) +{ + if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) + { + return TRUE; + } + return CDialogEx::PreTranslateMessage(pMsg); +} diff --git a/windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.h b/windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.h new file mode 100644 index 000000000..da7036b1f --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Multipath/CMultipathDlg.h @@ -0,0 +1,107 @@ +#pragma once +#include "AGVideoWnd.h" +#include +#include + +// CMultipathDlg dialog + +#define VIDEO_COUNT_MULTIPATH 2 +#define IDC_BASEWND_VIDEO_MULTIPATH 200 + +class CMultipathRtcEngineEventHandler + : public IRtcEngineEventHandler +{ +public: + //set the message notify window handler + void SetMsgReceiver(HWND hWnd) { m_hMsgHanlder = hWnd; } + + virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed) override; + virtual void onUserJoined(uid_t uid, int elapsed) override; + virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) override; + virtual void onLeaveChannel(const RtcStats& stats) override; + virtual void onMultipathStats(const MultipathStats& stats) override; + virtual void onNetworkTypeChanged(NETWORK_TYPE type) override; + +private: + HWND m_hMsgHanlder; +}; + +class CMultipathDlg : public CDialogEx +{ + DECLARE_DYNAMIC(CMultipathDlg) + +public: + CMultipathDlg(CWnd* pParent = nullptr); // standard constructor + virtual ~CMultipathDlg(); + + //Initialize the Agora SDK + bool InitAgora(); + //UnInitialize the Agora SDK + void UnInitAgora(); + + //resume window status + void ResumeStatus(); + +// Dialog Data + enum { IDD = IDD_DIALOG_MULTIPATH }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + virtual BOOL OnInitDialog(); + afx_msg void OnBnClickedButtonJoinchannel(); + afx_msg void OnSelchangeComboRole(); + afx_msg void OnSelchangeComboMultipathMode(); + afx_msg void OnBnClickedCheckEnableMultipath(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + + //Agora Event handler + afx_msg LRESULT OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDUserJoined(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDUserOffline(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDMultipathStats(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDNetworkTypeChanged(WPARAM wParam, LPARAM lParam); + +private: + //set control text from config. + void InitCtrlText(); + //create all video window to save m_videoWnds. + void CreateAllVideoWnds(); + //render local video from SDK local capture. + void RenderLocalVideo(); + //stop local video capture from SDK + void StopLocalVideo(); + void ResetVideoView(); + + IRtcEngine* m_rtcEngine = nullptr; + CMultipathRtcEngineEventHandler m_eventHandler; + bool m_joinChannel = false; + bool m_initialize = false; + //video wnd + CAGVideoWnd m_videoWnds[VIDEO_COUNT_MULTIPATH]; + std::list m_lstUids; + int m_uid = 0; + +public: + CComboBox m_cmbRole; + CStatic m_staRole; + CEdit m_edtChannelName; + CButton m_btnJoinChannel; + CListBox m_lstInfo; + CStatic m_videoArea; + CStatic m_staChannelName; + CComboBox m_cmbMultipathMode; + CStatic m_staMultipathMode; + CButton m_chkEnableMultipath; + CStatic m_staEnableMultipath; + + virtual BOOL PreTranslateMessage(MSG* pMsg); + +private: + std::string m_multipathModeStr = ""; + std::string m_networkStr = "unknown"; + int m_activePathNum = 0; +}; \ No newline at end of file diff --git a/windows/APIExample/APIExample/Advanced/OriginalAudio/CAgoraOriginalAudioDlg.cpp b/windows/APIExample/APIExample/Advanced/OriginalAudio/CAgoraOriginalAudioDlg.cpp index 13f15d4d7..8eb979be2 100755 --- a/windows/APIExample/APIExample/Advanced/OriginalAudio/CAgoraOriginalAudioDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/OriginalAudio/CAgoraOriginalAudioDlg.cpp @@ -227,7 +227,7 @@ void CAgoraOriginalAudioDlg::UnInitAgora() } //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.cpp b/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.cpp index aae24ec9a..c67f72578 100755 --- a/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.cpp @@ -84,7 +84,7 @@ void CAgoraOriginalVideoDlg::UnInitAgora() RegisterVideoFrameObserver(FALSE); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/PreCallTest/CAgoraPreCallTestDlg.cpp b/windows/APIExample/APIExample/Advanced/PreCallTest/CAgoraPreCallTestDlg.cpp index eb3f97c98..5dabf7634 100755 --- a/windows/APIExample/APIExample/Advanced/PreCallTest/CAgoraPreCallTestDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/PreCallTest/CAgoraPreCallTestDlg.cpp @@ -54,10 +54,10 @@ BEGIN_MESSAGE_MAP(CAgoraPreCallTestDlg, CDialogEx) ON_MESSAGE(WM_MSGID(EID_LASTMILE_PROBE_RESULT), &CAgoraPreCallTestDlg::OnEIDLastmileProbeResult) ON_MESSAGE(WM_MSGID(EID_LASTMILE_QUAILTY), &CAgoraPreCallTestDlg::OnEIDLastmileQuality) ON_MESSAGE(WM_MSGID(EID_AUDIO_VOLUME_INDICATION), &CAgoraPreCallTestDlg::OnEIDAudioVolumeIndication) - ON_WM_PAINT() - ON_BN_CLICKED(IDC_BUTTON_AUDIO_ECHO_TEST, &CAgoraPreCallTestDlg::OnBnClickedButtonAudioEchoTest) - ON_WM_TIMER() - ON_BN_CLICKED(IDC_BUTTON_VIDEO_ECHO_TEST, &CAgoraPreCallTestDlg::OnBnClickedButtonVideoEchoTest) + ON_WM_PAINT() + ON_BN_CLICKED(IDC_BUTTON_AUDIO_ECHO_TEST, &CAgoraPreCallTestDlg::OnBnClickedButtonAudioEchoTest) + ON_WM_TIMER() + ON_BN_CLICKED(IDC_BUTTON_VIDEO_ECHO_TEST, &CAgoraPreCallTestDlg::OnBnClickedButtonVideoEchoTest) END_MESSAGE_MAP() //init ctrl text. @@ -95,14 +95,14 @@ bool CAgoraPreCallTestDlg::InitAgora() context.eventHandler = &m_eventHandler; //initialize the Agora RTC engine context. int ret = m_rtcEngine->initialize(context); - if (ret != 0) { - m_initialize = false; - CString strInfo; - strInfo.Format(_T("initialize failed: %d"), ret); - m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); - return false; - } - else + if (ret != 0) { + m_initialize = false; + CString strInfo; + strInfo.Format(_T("initialize failed: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + return false; + } + else m_initialize = true; m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("initialize success")); LastmileProbeConfig config; @@ -138,7 +138,7 @@ void CAgoraPreCallTestDlg::UnInitAgora() m_videoDeviceManager->release(); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } @@ -437,77 +437,77 @@ void CAgoraPreCallTestDlg::OnPaint() //draw quality bitmap m_imgNetQuality.Draw(&dc, m_netQuality, CPoint(16, 40), ILD_NORMAL); } - - - - -void CAgoraPreCallTestDlg::OnBnClickedButtonAudioEchoTest() -{ - if (!m_audioEchoTest) { - EchoTestConfiguration config; - config.channelId = "AudioEchoTestChannel"; - config.token = ""; - config.enableAudio = true; - config.enableVideo = false; - config.intervalInSeconds = m_audioEchoInterval; - m_rtcEngine->startEchoTest(config); - m_audioEchoTimeIndex = 0; - m_audioEchoTest = true; - SetTimer(m_audioEchoTimeId, 1000, NULL); - m_btnAudioEchoTest.SetWindowTextW(PerCallTestCtrlStopTest); - } - else { - m_rtcEngine->stopEchoTest(); - m_audioEchoTest = false; - m_audioEchoTimeIndex = 0; - KillTimer(m_audioEchoTimeId); - m_btnAudioEchoTest.SetWindowTextW(PerCallTestCtrlStartTest); - m_staAudioEchoTestTip.SetWindowTextW(PerCallTestCtrlWaitingStart); - } -} - -void CAgoraPreCallTestDlg::OnTimer(UINT_PTR nIDEvents) { - if (nIDEvents != m_audioEchoTimeId || !m_audioEchoTest) { - return; - } - m_audioEchoTimeIndex++; - int diff = m_audioEchoInterval - m_audioEchoTimeIndex; - if (diff >= 0) { - CString str; - str.Format(PerCallTestCtrlRecording, diff); - m_staAudioEchoTestTip.SetWindowTextW(str); - } - else if( diff >= -1 * m_audioEchoInterval){ - CString str; - str.Format(PerCallTestCtrlPlaying, -diff); - m_staAudioEchoTestTip.SetWindowTextW(str); - } - else { - OnBnClickedButtonAudioEchoTest(); - } -} - - - -void CAgoraPreCallTestDlg::OnBnClickedButtonVideoEchoTest() -{ - if (!m_videoEchoTest) { - EchoTestConfiguration config; - config.channelId = "VideoEchoTestChannel"; - config.token = ""; - config.enableAudio = false; - config.enableVideo = true; - config.view = m_VideoTest.GetVideoSafeHwnd(); - config.intervalInSeconds = m_videoEchoInterval; - int ret = m_rtcEngine->startEchoTest(config); - m_videoEchoTest = true; - m_btnVideoEchoTest.SetWindowTextW(PerCallTestCtrlStopTest); - m_btnVideoTest.EnableWindow(FALSE); - } - else { - m_rtcEngine->stopEchoTest(); - m_videoEchoTest = false; - m_btnVideoEchoTest.SetWindowTextW(PerCallTestCtrlStartTest); - m_btnVideoTest.EnableWindow(TRUE); - } -} + + + + +void CAgoraPreCallTestDlg::OnBnClickedButtonAudioEchoTest() +{ + if (!m_audioEchoTest) { + EchoTestConfiguration config; + config.channelId = "AudioEchoTestChannel"; + config.token = ""; + config.enableAudio = true; + config.enableVideo = false; + config.intervalInSeconds = m_audioEchoInterval; + m_rtcEngine->startEchoTest(config); + m_audioEchoTimeIndex = 0; + m_audioEchoTest = true; + SetTimer(m_audioEchoTimeId, 1000, NULL); + m_btnAudioEchoTest.SetWindowTextW(PerCallTestCtrlStopTest); + } + else { + m_rtcEngine->stopEchoTest(); + m_audioEchoTest = false; + m_audioEchoTimeIndex = 0; + KillTimer(m_audioEchoTimeId); + m_btnAudioEchoTest.SetWindowTextW(PerCallTestCtrlStartTest); + m_staAudioEchoTestTip.SetWindowTextW(PerCallTestCtrlWaitingStart); + } +} + +void CAgoraPreCallTestDlg::OnTimer(UINT_PTR nIDEvents) { + if (nIDEvents != m_audioEchoTimeId || !m_audioEchoTest) { + return; + } + m_audioEchoTimeIndex++; + int diff = m_audioEchoInterval - m_audioEchoTimeIndex; + if (diff >= 0) { + CString str; + str.Format(PerCallTestCtrlRecording, diff); + m_staAudioEchoTestTip.SetWindowTextW(str); + } + else if( diff >= -1 * m_audioEchoInterval){ + CString str; + str.Format(PerCallTestCtrlPlaying, -diff); + m_staAudioEchoTestTip.SetWindowTextW(str); + } + else { + OnBnClickedButtonAudioEchoTest(); + } +} + + + +void CAgoraPreCallTestDlg::OnBnClickedButtonVideoEchoTest() +{ + if (!m_videoEchoTest) { + EchoTestConfiguration config; + config.channelId = "VideoEchoTestChannel"; + config.token = ""; + config.enableAudio = false; + config.enableVideo = true; + config.view = m_VideoTest.GetVideoSafeHwnd(); + config.intervalInSeconds = m_videoEchoInterval; + int ret = m_rtcEngine->startEchoTest(config); + m_videoEchoTest = true; + m_btnVideoEchoTest.SetWindowTextW(PerCallTestCtrlStopTest); + m_btnVideoTest.EnableWindow(FALSE); + } + else { + m_rtcEngine->stopEchoTest(); + m_videoEchoTest = false; + m_btnVideoEchoTest.SetWindowTextW(PerCallTestCtrlStartTest); + m_btnVideoTest.EnableWindow(TRUE); + } +} diff --git a/windows/APIExample/APIExample/Advanced/PushExternalVideoYUV/PushExternalVideoYUV.cpp b/windows/APIExample/APIExample/Advanced/PushExternalVideoYUV/PushExternalVideoYUV.cpp index 3763dbae8..55016324d 100755 --- a/windows/APIExample/APIExample/Advanced/PushExternalVideoYUV/PushExternalVideoYUV.cpp +++ b/windows/APIExample/APIExample/Advanced/PushExternalVideoYUV/PushExternalVideoYUV.cpp @@ -167,7 +167,7 @@ void PushExternalVideoYUV::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/RTMPStream/AgoraRtmpStreaming.cpp b/windows/APIExample/APIExample/Advanced/RTMPStream/AgoraRtmpStreaming.cpp index 80bb6ab49..499cd078d 100755 --- a/windows/APIExample/APIExample/Advanced/RTMPStream/AgoraRtmpStreaming.cpp +++ b/windows/APIExample/APIExample/Advanced/RTMPStream/AgoraRtmpStreaming.cpp @@ -249,7 +249,7 @@ void CAgoraRtmpStreamingDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/RTMPinject/AgoraRtmpInjectionDlg.cpp b/windows/APIExample/APIExample/Advanced/RTMPinject/AgoraRtmpInjectionDlg.cpp index d7344a62a..9c4c67ca4 100755 --- a/windows/APIExample/APIExample/Advanced/RTMPinject/AgoraRtmpInjectionDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/RTMPinject/AgoraRtmpInjectionDlg.cpp @@ -12,7 +12,7 @@ is called without a user ID specified. The server will automatically assign one parameters: channel:channel name. - uid: user ID。If the UID is specified in the joinChannel, that ID is returned here; + uid: user ID锟斤拷If the UID is specified in the joinChannel, that ID is returned here; Otherwise, use the ID automatically assigned by the Agora server. elapsed: The Time from the joinChannel until this event occurred (ms). */ @@ -76,7 +76,7 @@ void CAgoraRtmpInjectionRtcEngineEventHandler::onLeaveChannel(const RtcStats& st parameters: uid: remote user/anchor ID for newly added channel. elapsed: The joinChannel is called from the local user to the delay triggered - by the callback(ms). + by the callback锟斤拷ms). */ void CAgoraRtmpInjectionRtcEngineEventHandler::onUserJoined(uid_t uid, int elapsed) { @@ -228,7 +228,7 @@ void CAgoraRtmpInjectionDlg::UnInitAgora() m_rtcEngine->disableVideo(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; } @@ -413,39 +413,39 @@ LRESULT CAgoraRtmpInjectionDlg::OnEIDStreamInjectedStatus(WPARAM wParam, LPARAM switch ((INJECT_STREAM_STATUS)lParam) { case INJECT_STREAM_STATUS_START_SUCCESS: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStartSucc, 0); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStartSucc, 0); break; case INJECT_STREAM_STATUS_START_ALREADY_EXISTS: - strInfo.Format(_T("%s, err: %d。"), agoraInjectExist, 1); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectExist, 1); break; case INJECT_STREAM_STATUS_START_UNAUTHORIZED: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStartUnAuth, 2); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStartUnAuth, 2); break; case INJECT_STREAM_STATUS_START_TIMEDOUT: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStartTimeout, 3); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStartTimeout, 3); break; case INJECT_STREAM_STATUS_START_FAILED: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStartFailed, 4); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStartFailed, 4); break; case INJECT_STREAM_STATUS_STOP_SUCCESS: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStopSuccess, 5); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStopSuccess, 5); break; case INJECT_STREAM_STATUS_STOP_NOT_FOUND: - strInfo.Format(_T("%s, err: %d。"), agoraInjectNotFound, 6); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectNotFound, 6); break; case INJECT_STREAM_STATUS_STOP_UNAUTHORIZED: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStopUnAuth, 7); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStopUnAuth, 7); break; case INJECT_STREAM_STATUS_STOP_TIMEDOUT: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStopTimeout, 8); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStopTimeout, 8); break; case INJECT_STREAM_STATUS_STOP_FAILED: - strInfo.Format(_T("%s, err: %d。"), agoraInjectStopFailed, 9); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectStopFailed, 9); break; case INJECT_STREAM_STATUS_BROKEN: - strInfo.Format(_T("%s, err: %d。"), agoraInjectBroken, 10); + strInfo.Format(_T("%s, err: %d锟斤拷"), agoraInjectBroken, 10); break; default: break; diff --git a/windows/APIExample/APIExample/Advanced/RegionConn/CAgoraRegionConnDlg.cpp b/windows/APIExample/APIExample/Advanced/RegionConn/CAgoraRegionConnDlg.cpp index fa9d1963b..cf7b33db4 100644 --- a/windows/APIExample/APIExample/Advanced/RegionConn/CAgoraRegionConnDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/RegionConn/CAgoraRegionConnDlg.cpp @@ -168,7 +168,7 @@ void CAgoraRegionConnDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/ReportInCall/CAgoraReportInCallDlg.cpp b/windows/APIExample/APIExample/Advanced/ReportInCall/CAgoraReportInCallDlg.cpp index cf37109ea..3f57c32a2 100644 --- a/windows/APIExample/APIExample/Advanced/ReportInCall/CAgoraReportInCallDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/ReportInCall/CAgoraReportInCallDlg.cpp @@ -137,7 +137,7 @@ void CAgoraReportInCallDlg::UnInitAgora() m_rtcEngine->disableVideo(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); m_rtcEngine = NULL; } diff --git a/windows/APIExample/APIExample/Advanced/ScreenShare/AgoraScreenCapture.cpp b/windows/APIExample/APIExample/Advanced/ScreenShare/AgoraScreenCapture.cpp index cf87b40cc..728d98052 100755 --- a/windows/APIExample/APIExample/Advanced/ScreenShare/AgoraScreenCapture.cpp +++ b/windows/APIExample/APIExample/Advanced/ScreenShare/AgoraScreenCapture.cpp @@ -124,7 +124,7 @@ void CAgoraScreenCapture::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.cpp b/windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.cpp new file mode 100644 index 000000000..01d064dc4 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.cpp @@ -0,0 +1,640 @@ +// CSimulcastDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "APIExample.h" +#include "CSimulcastDlg.h" + +void CSimulcastRtcEngineEventHandler::onJoinChannelSuccess(const char *channel, uid_t uid, int elapsed) +{ + if (m_hMsgHanlder) { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_JOINCHANNEL_SUCCESS), (WPARAM)uid, (LPARAM)elapsed); + } +} + +void CSimulcastRtcEngineEventHandler::onUserJoined(uid_t uid, int elapsed) +{ + if (m_hMsgHanlder) { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_USER_JOINED), (WPARAM)uid, (LPARAM)elapsed); + } +} + +void CSimulcastRtcEngineEventHandler::onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) +{ + if (m_hMsgHanlder) { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_USER_OFFLINE), (WPARAM)uid, (LPARAM)reason); + } +} + +void CSimulcastRtcEngineEventHandler::onLeaveChannel(const RtcStats &stats) +{ + if (m_hMsgHanlder) { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LEAVE_CHANNEL), 0, 0); + } +} + +void CSimulcastRtcEngineEventHandler::onRemoteVideoStats(const RemoteVideoStats &stats) +{ + if (m_hMsgHanlder) { + RemoteVideoStats* s = new RemoteVideoStats; + *s = stats; + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_REMOTE_VIDEO_STATS), (WPARAM)s, 0); + } +} + +// CSimulcastDlg dialog +IMPLEMENT_DYNAMIC(CSimulcastDlg, CDialogEx) + +CSimulcastDlg::CSimulcastDlg(CWnd *pParent /*=nullptr*/) +: CDialogEx(IDD_DIALOG_SIMULCAST, pParent) +{ +} + +CSimulcastDlg::~CSimulcastDlg() +{ +} + +void CSimulcastDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_COMBO_ROLE, m_cmbRole); + DDX_Control(pDX, IDC_STATIC_ROLE, m_staRole); + DDX_Control(pDX, IDC_EDIT_CHANNELNAME, m_edtChannelName); + DDX_Control(pDX, IDC_BUTTON_JOINCHANNEL, m_btnJoinChannel); + DDX_Control(pDX, IDC_LIST_INFO_SIMULCAST, m_lstInfo); + DDX_Control(pDX, IDC_STATIC_VIDEO, m_videoArea); + DDX_Control(pDX, IDC_STATIC_CHANNELNAME, m_staChannelName); + + // Broadcaster layer checkboxes + DDX_Control(pDX, IDC_CHECK_LAYER1, m_chkLayer1); + DDX_Control(pDX, IDC_CHECK_LAYER2, m_chkLayer2); + DDX_Control(pDX, IDC_CHECK_LAYER3, m_chkLayer3); + DDX_Control(pDX, IDC_CHECK_LAYER4, m_chkLayer4); + DDX_Control(pDX, IDC_STATIC_LAYER_TITLE, m_staLayerTitle); + + // Audience layer selection + DDX_Control(pDX, IDC_COMBO_LAYER_SELECT, m_cmbLayerSelect); + DDX_Control(pDX, IDC_STATIC_LAYER_SELECT, m_staLayerSelect); +} + +BEGIN_MESSAGE_MAP(CSimulcastDlg, CDialogEx) +ON_BN_CLICKED(IDC_BUTTON_JOINCHANNEL, &CSimulcastDlg::OnBnClickedButtonJoinchannel) +ON_CBN_SELCHANGE(IDC_COMBO_ROLE, &CSimulcastDlg::OnSelchangeComboRole) +ON_BN_CLICKED(IDC_CHECK_LAYER1, &CSimulcastDlg::OnBnClickedCheckLayer1) +ON_BN_CLICKED(IDC_CHECK_LAYER2, &CSimulcastDlg::OnBnClickedCheckLayer2) +ON_BN_CLICKED(IDC_CHECK_LAYER3, &CSimulcastDlg::OnBnClickedCheckLayer3) +ON_BN_CLICKED(IDC_CHECK_LAYER4, &CSimulcastDlg::OnBnClickedCheckLayer4) +ON_CBN_SELCHANGE(IDC_COMBO_LAYER_SELECT, &CSimulcastDlg::OnSelchangeComboLayerSelect) +ON_MESSAGE(WM_MSGID(EID_JOINCHANNEL_SUCCESS), &CSimulcastDlg::OnEIDJoinChannelSuccess) +ON_MESSAGE(WM_MSGID(EID_LEAVE_CHANNEL), &CSimulcastDlg::OnEIDLeaveChannel) +ON_MESSAGE(WM_MSGID(EID_USER_JOINED), &CSimulcastDlg::OnEIDUserJoined) +ON_MESSAGE(WM_MSGID(EID_USER_OFFLINE), &CSimulcastDlg::OnEIDUserOffline) +ON_MESSAGE(WM_MSGID(EID_REMOTE_VIDEO_STATS), &CSimulcastDlg::OnEIDRemoteVideoStats) +ON_WM_SHOWWINDOW() +END_MESSAGE_MAP() + +// CSimulcastDlg message handlers +BOOL CSimulcastDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + m_eventHandler.SetMsgReceiver(m_hWnd); + + InitCtrlText(); + CreateAllVideoWnds(); + + // Initialize role combo box + m_cmbRole.InsertString(0, agoraRoleBroadcaster); + m_cmbRole.InsertString(1, agoraRoleAudience); + m_cmbRole.SetCurSel(0); + + // Initialize layer selection combo box for audience + m_cmbLayerSelect.InsertString(0, _T("Layer 1:720p30fps")); + m_cmbLayerSelect.InsertString(1, _T("Layer 2:540p15fps")); + m_cmbLayerSelect.InsertString(2, _T("Layer 3:360p15fps")); + m_cmbLayerSelect.InsertString(3, _T("Layer 4:270p15fps")); + m_cmbLayerSelect.SetCurSel(0); + + UpdateUIForRole(); + + return TRUE; +} + +void CSimulcastDlg::InitCtrlText() +{ + m_staRole.SetWindowText(commonCtrlClientRole); + m_staChannelName.SetWindowText(commonCtrlChannel); + m_btnJoinChannel.SetWindowText(commonCtrlJoinChannel); + m_staLayerTitle.SetWindowText(_T("Simulcast Layers:")); + m_staLayerSelect.SetWindowText(_T("Select Layer:")); +} + +void CSimulcastDlg::CreateAllVideoWnds() +{ + for (int i = 0; i < VIDEO_COUNT_SIMULCAST; i++) + { + m_videoWnds[i].Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 1, 1), this, IDC_BASEWND_VIDEO_SIMULCAST + i); + m_videoWnds[i].ShowWindow(SW_SHOW); + } + + ResetVideoView(); +} + +void CSimulcastDlg::ResetVideoView() +{ + // 闅愯棌瑙嗛鍖哄煙鑳屾櫙 + m_videoArea.ShowWindow(SW_HIDE); + + CRect rcArea; + m_videoArea.GetClientRect(&rcArea); + + int nViewWidth = rcArea.Width() / 2; + int nViewHeight = rcArea.Height(); + + for (int i = 0; i < VIDEO_COUNT_SIMULCAST; i++) + { + CRect rcVideoArea(i * nViewWidth, 0, (i + 1) * nViewWidth, nViewHeight); + m_videoWnds[i].MoveWindow(&rcVideoArea, TRUE); + m_videoWnds[i].SetUID(0); + m_videoWnds[i].SetParent(this); + m_videoWnds[i].ShowWindow(SW_SHOW); + m_videoWnds[i].Invalidate(); + } +} + +bool CSimulcastDlg::InitAgora() +{ + //create Agora RTC engine + m_rtcEngine = createAgoraRtcEngine(); + if (!m_rtcEngine) { + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("createAgoraRtcEngine failed")); + return false; + } + //set message notify receiver window + m_eventHandler.SetMsgReceiver(m_hWnd); + + RtcEngineContext context; + std::string strAppID = GET_APP_ID; + context.appId = strAppID.c_str(); + context.eventHandler = &m_eventHandler; + //initialize the Agora RTC engine context. + int ret = m_rtcEngine->initialize(context); + if (ret != 0) { + m_initialize = false; + CString strInfo; + strInfo.Format(_T("initialize failed: %d"), ret); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + return false; + } + else + m_initialize = true; + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("initialize success")); + + //enable video in the engine. + m_rtcEngine->enableVideo(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("enable video")); + + //set channel profile in the engine to the CHANNEL_PROFILE_LIVE_BROADCASTING. + m_rtcEngine->setChannelProfile(CHANNEL_PROFILE_LIVE_BROADCASTING); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("live broadcasting")); + + //set client role + CLIENT_ROLE_TYPE role = m_cmbRole.GetCurSel() == 0 ? CLIENT_ROLE_BROADCASTER : CLIENT_ROLE_AUDIENCE; + m_rtcEngine->setClientRole(role); + + // Setup video encoding configuration for simulcast + VideoEncoderConfiguration config; + config.dimensions.width = 1280; + config.dimensions.height = 720; + config.frameRate = FRAME_RATE_FPS_30; + config.bitrate = STANDARD_BITRATE; + config.orientationMode = ORIENTATION_MODE_ADAPTIVE; + m_rtcEngine->setVideoEncoderConfiguration(config); + + return true; +} + +void CSimulcastDlg::UnInitAgora() +{ + if (m_rtcEngine) { + if (m_joinChannel) + //leave channel + m_joinChannel = !m_rtcEngine->leaveChannel(); + //stop preview in the engine. + m_rtcEngine->stopPreview(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("stopPreview")); + //disable video in the engine. + m_rtcEngine->disableVideo(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); + //release engine. + if (m_initialize) { + m_rtcEngine->release(nullptr); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release")); + } + m_rtcEngine = NULL; + } +} + +void CSimulcastDlg::ResumeStatus() +{ + InitAgora(); + m_lstInfo.ResetContent(); + m_cmbRole.SetCurSel(0); + m_joinChannel = false; + m_initialize = false; + UpdateUIForRole(); +} + +void CSimulcastDlg::RenderLocalVideo() +{ + if (m_rtcEngine) { + //enable local video in the engine. + m_rtcEngine->enableLocalVideo(true); + //start preview in the engine. + m_rtcEngine->startPreview(); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("startPreview")); + VideoCanvas canvas; + canvas.renderMode = media::base::RENDER_MODE_HIDDEN; + canvas.uid = 0; + canvas.view = m_videoWnds[0].GetSafeHwnd(); + //setup local video in the engine to canvas. + m_rtcEngine->setupLocalVideo(canvas); + m_videoWnds[0].SetUID(canvas.uid); + CString strInfo; + strInfo.Format(_T("setupLocalVideo uid: %u"), canvas.uid); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + } +} + +void CSimulcastDlg::StopLocalVideo() +{ + if (m_rtcEngine) { + //stop preview in the engine. + m_rtcEngine->stopPreview(); + //disable local video in the engine. + m_rtcEngine->enableLocalVideo(false); + VideoCanvas canvas; + canvas.view = NULL; + canvas.uid = 0; + //setup local video in the engine to canvas. + m_rtcEngine->setupLocalVideo(canvas); + m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("setupLocalVideo NULL")); + } +} + +void CSimulcastDlg::UpdateUIForRole() +{ + int role = m_cmbRole.GetCurSel(); + + if (role == 0) { // Broadcaster + // Show layer checkboxes + m_chkLayer1.ShowWindow(SW_SHOW); + m_chkLayer2.ShowWindow(SW_SHOW); + m_chkLayer3.ShowWindow(SW_SHOW); + m_chkLayer4.ShowWindow(SW_SHOW); + m_staLayerTitle.ShowWindow(SW_SHOW); + + // Hide layer selection combo + m_cmbLayerSelect.ShowWindow(SW_HIDE); + m_staLayerSelect.ShowWindow(SW_HIDE); + + // Set checkbox labels + m_chkLayer1.SetWindowText(_T("Layer 1:720p30fps")); + m_chkLayer2.SetWindowText(_T("Layer 2:540p15fps")); + m_chkLayer3.SetWindowText(_T("Layer 3:360p15fps")); + m_chkLayer4.SetWindowText(_T("Layer 4:270p15fps")); + + // Default check first layer + m_chkLayer1.SetCheck(BST_CHECKED); + } + else { // Audience + // Hide layer checkboxes + m_chkLayer1.ShowWindow(SW_HIDE); + m_chkLayer2.ShowWindow(SW_HIDE); + m_chkLayer3.ShowWindow(SW_HIDE); + m_chkLayer4.ShowWindow(SW_HIDE); + m_staLayerTitle.ShowWindow(SW_HIDE); + + // Show layer selection combo + m_cmbLayerSelect.ShowWindow(SW_SHOW); + m_staLayerSelect.ShowWindow(SW_SHOW); + } +} + +void CSimulcastDlg::OnBnClickedButtonJoinchannel() +{ + if (!m_rtcEngine || !m_initialize) + return; + CString strInfo; + if (!m_joinChannel) { + CString strChannelName; + m_edtChannelName.GetWindowText(strChannelName); + if (strChannelName.IsEmpty()) { + AfxMessageBox(_T("Fill channel name first")); + return; + } + + // set simulcast config + if (m_cmbRole.GetCurSel() == 0) { // Broadcaster + ConfigureSimulcast(); + } + + std::string szChannelId = cs2utf8(strChannelName); + //join channel in the engine. + if (0 == m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.c_str(), "", 0)) { + strInfo.Format(_T("join channel %s"), getCurrentTime()); + m_btnJoinChannel.EnableWindow(FALSE); + } + } + else { + //leave channel in the engine. + if (0 == m_rtcEngine->leaveChannel()) { + strInfo.Format(_T("leave channel %s"), getCurrentTime()); + } + } + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); +} + +void CSimulcastDlg::OnSelchangeComboRole() +{ + int nSel = m_cmbRole.GetCurSel(); + if (m_rtcEngine != NULL) + m_rtcEngine->setClientRole(nSel == 0 ? CLIENT_ROLE_BROADCASTER : CLIENT_ROLE_AUDIENCE); + + UpdateUIForRole(); + + CString strInfo; + strInfo.Format(_T("setClientRole changed to %s"), nSel == 0 ? _T("Broadcaster") : _T("Audience")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); +} + +int CSimulcastDlg::GetCheckedLayerCount() +{ + int count = 0; + if (m_chkLayer1.GetCheck() == BST_CHECKED) count++; + if (m_chkLayer2.GetCheck() == BST_CHECKED) count++; + if (m_chkLayer3.GetCheck() == BST_CHECKED) count++; + if (m_chkLayer4.GetCheck() == BST_CHECKED) count++; + return count; +} + +void CSimulcastDlg::OnBnClickedCheckLayer1() +{ + if (m_chkLayer1.GetCheck() == BST_CHECKED && GetCheckedLayerCount() > 3) { + m_chkLayer1.SetCheck(BST_UNCHECKED); + AfxMessageBox(_T("Maximum 3 simulcast layers can be enabled simultaneously")); + return; + } + + CString strInfo; + strInfo.Format(_T("Layer 1 %s"), m_chkLayer1.GetCheck() ? _T("enabled") : _T("disabled")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // Update simulcast configuration when joined + if (m_joinChannel) { + ConfigureSimulcast(); + } +} + +void CSimulcastDlg::OnBnClickedCheckLayer2() +{ + if (m_chkLayer2.GetCheck() == BST_CHECKED && GetCheckedLayerCount() > 3) { + m_chkLayer2.SetCheck(BST_UNCHECKED); + AfxMessageBox(_T("Maximum 3 simulcast layers can be enabled simultaneously")); + return; + } + + CString strInfo; + strInfo.Format(_T("Layer 2 %s"), m_chkLayer2.GetCheck() ? _T("enabled") : _T("disabled")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // Update simulcast configuration when joined + if (m_joinChannel) { + ConfigureSimulcast(); + } +} + +void CSimulcastDlg::OnBnClickedCheckLayer3() +{ + if (m_chkLayer3.GetCheck() == BST_CHECKED && GetCheckedLayerCount() > 3) { + m_chkLayer3.SetCheck(BST_UNCHECKED); + AfxMessageBox(_T("Maximum 3 simulcast layers can be enabled simultaneously")); + return; + } + + CString strInfo; + strInfo.Format(_T("Layer 3 %s"), m_chkLayer3.GetCheck() ? _T("enabled") : _T("disabled")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // Update simulcast configuration when joined + if (m_joinChannel) { + ConfigureSimulcast(); + } +} + +void CSimulcastDlg::OnBnClickedCheckLayer4() +{ + if (m_chkLayer4.GetCheck() == BST_CHECKED && GetCheckedLayerCount() > 3) { + m_chkLayer4.SetCheck(BST_UNCHECKED); + AfxMessageBox(_T("Maximum 3 simulcast layers can be enabled simultaneously")); + return; + } + + CString strInfo; + strInfo.Format(_T("Layer 4 %s"), m_chkLayer4.GetCheck() ? _T("enabled") : _T("disabled")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // Update simulcast configuration when joined + if (m_joinChannel) { + ConfigureSimulcast(); + } +} + +void CSimulcastDlg::OnSelchangeComboLayerSelect() +{ + int sel = m_cmbLayerSelect.GetCurSel(); + CString strInfo; + strInfo.Format(_T("Selected layer: %d"), sel + 1); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // For audience, set remote video stream type based on selected layer + if (m_cmbRole.GetCurSel() == 1 && m_rtcEngine && m_joinChannel) { // Audience + VIDEO_STREAM_TYPE streamType; + switch (sel) { + case 0: // Layer 1 (High) + streamType = VIDEO_STREAM_LAYER_1; + break; + case 1: // Layer 2 (Medium) + streamType = VIDEO_STREAM_LAYER_2; + break; + case 2: // Layer 3 (Low) + streamType = VIDEO_STREAM_LAYER_3; + break; + case 3: // Layer 4 (Ultra Low) + streamType = VIDEO_STREAM_LAYER_4; + break; + default: + streamType = VIDEO_STREAM_LAYER_1; + break; + } + + // Apply to all remote users + for (int i = 1; i < VIDEO_COUNT_SIMULCAST; i++) { + uid_t uid = m_videoWnds[i].GetUID(); + if (uid != 0) { + m_rtcEngine->setRemoteVideoStreamType(uid, streamType); + } + } + } +} + +void CSimulcastDlg::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialogEx::OnShowWindow(bShow, nStatus); + if (bShow)//bShwo is true ,show window + { + InitAgora(); + RenderLocalVideo(); + } + else { + ResumeStatus(); + } +} + +LRESULT CSimulcastDlg::OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam) +{ + m_joinChannel = true; + m_btnJoinChannel.EnableWindow(TRUE); + m_btnJoinChannel.SetWindowText(commonCtrlLeaveChannel); + CString strInfo; + strInfo.Format(_T("onJoinChannelSuccess: uid=%u"), wParam); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + + //notify parent window + ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(EID_JOINCHANNEL_SUCCESS), TRUE, 0); + return 0; +} + +LRESULT CSimulcastDlg::OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam) +{ + m_joinChannel = false; + m_btnJoinChannel.SetWindowText(commonCtrlJoinChannel); + CString strInfo; + strInfo.Format(_T("onLeaveChannel")); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + //notify parent window + ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(EID_JOINCHANNEL_SUCCESS), FALSE, 0); + return 0; +} + +LRESULT CSimulcastDlg::OnEIDUserJoined(WPARAM wParam, LPARAM lParam) +{ + uid_t remoteUid = (uid_t)wParam; + VideoCanvas canvas; + canvas.renderMode = media::base::RENDER_MODE_HIDDEN; + canvas.uid = remoteUid; + canvas.view = m_videoWnds[1].GetSafeHwnd(); + //setup remote video in the engine to canvas. + m_rtcEngine->setupRemoteVideo(canvas); + m_videoWnds[1].SetUID(canvas.uid); + CString strInfo; + strInfo.Format(_T("onUserJoined: uid=%u"), remoteUid); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + return 0; +} + +LRESULT CSimulcastDlg::OnEIDUserOffline(WPARAM wParam, LPARAM lParam) +{ + uid_t remoteUid = (uid_t)wParam; + VideoCanvas canvas; + canvas.view = NULL; + canvas.uid = remoteUid; + //setup remote video in the engine to canvas. + m_rtcEngine->setupRemoteVideo(canvas); + m_videoWnds[1].SetUID(0); + m_videoWnds[1].Invalidate(); + CString strInfo; + strInfo.Format(_T("onUserOffline: uid=%u"), remoteUid); + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + m_lstInfo.SetCurSel(m_lstInfo.GetCount() - 1); + return 0; +} + +LRESULT CSimulcastDlg::OnEIDRemoteVideoStats(WPARAM wParam, LPARAM lParam) +{ + // RemoteVideoStats* p = reinterpret_cast(wParam); + // if (p) + // { + // CString strInfo = _T("===onRemoteVideoStats==="); + // m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // strInfo.Format(_T("uid:%u"), p->uid); + // m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + // strInfo.Format(_T("delay:%d"), p->delay); + // m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + + // strInfo.Format(_T("width:%d"), p->width); + // m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + // strInfo.Format(_T("height:%d"), p->height); + // m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + // delete p; + // } + return 0; +} + +BOOL CSimulcastDlg::PreTranslateMessage(MSG* pMsg) +{ + if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) { + return TRUE; + } + return CDialogEx::PreTranslateMessage(pMsg); +} + +void CSimulcastDlg::ConfigureSimulcast() +{ + if (!m_rtcEngine || !m_initialize) { + return; + } + + // Configure simulcast only for broadcaster + if (m_cmbRole.GetCurSel() == 0) { // Broadcaster + SimulcastConfig simulcastConfig; + + // Layer 1 (High quality) + simulcastConfig.configs[0].dimensions.width = 1280; + simulcastConfig.configs[0].dimensions.height = 720; + simulcastConfig.configs[0].framerate = 30; + simulcastConfig.configs[0].enable = m_chkLayer1.GetCheck() == BST_CHECKED; + + // Layer 2 (Medium quality) + simulcastConfig.configs[1].dimensions.width = 960; + simulcastConfig.configs[1].dimensions.height = 540; + simulcastConfig.configs[1].framerate = 15; + simulcastConfig.configs[1].enable = m_chkLayer2.GetCheck() == BST_CHECKED; + + // Layer 3 (Low quality) + simulcastConfig.configs[2].dimensions.width = 640; + simulcastConfig.configs[2].dimensions.height = 360; + simulcastConfig.configs[2].framerate = 15; + simulcastConfig.configs[2].enable = m_chkLayer3.GetCheck() == BST_CHECKED; + + // Layer 4 (Ultra low quality) + simulcastConfig.configs[3].dimensions.width = 480; + simulcastConfig.configs[3].dimensions.height = 270; + simulcastConfig.configs[3].framerate = 15; + simulcastConfig.configs[3].enable = m_chkLayer4.GetCheck() == BST_CHECKED; + + // Apply simulcast configuration + int ret = m_rtcEngine->setSimulcastConfig(simulcastConfig); + CString strInfo; + if (ret == 0) { + strInfo.Format(_T("Simulcast config applied successfully")); + } else { + strInfo.Format(_T("Simulcast config failed: %d"), ret); + } + m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); + } +} \ No newline at end of file diff --git a/windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.h b/windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.h new file mode 100644 index 000000000..1cf96bd7c --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/Simulcast/CSimulcastDlg.h @@ -0,0 +1,121 @@ +#pragma once +#include "AGVideoWnd.h" +#include +#include + +// CSimulcastDlg dialog + +#define VIDEO_COUNT_SIMULCAST 2 +#define IDC_BASEWND_VIDEO_SIMULCAST 300 + +class CSimulcastRtcEngineEventHandler + : public IRtcEngineEventHandler +{ +public: + //set the message notify window handler + void SetMsgReceiver(HWND hWnd) { m_hMsgHanlder = hWnd; } + + virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed) override; + virtual void onUserJoined(uid_t uid, int elapsed) override; + virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) override; + virtual void onLeaveChannel(const RtcStats& stats) override; + virtual void onRemoteVideoStats(const RemoteVideoStats& stats) override; + +private: + HWND m_hMsgHanlder; +}; + +class CSimulcastDlg : public CDialogEx +{ + DECLARE_DYNAMIC(CSimulcastDlg) + +public: + CSimulcastDlg(CWnd* pParent = nullptr); // standard constructor + virtual ~CSimulcastDlg(); + + //Initialize the Agora SDK + bool InitAgora(); + //UnInitialize the Agora SDK + void UnInitAgora(); + + //resume window status + void ResumeStatus(); + +// Dialog Data + enum { IDD = IDD_DIALOG_SIMULCAST }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + virtual BOOL OnInitDialog(); + afx_msg void OnBnClickedButtonJoinchannel(); + afx_msg void OnSelchangeComboRole(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + + // Layer checkbox handlers for broadcaster + afx_msg void OnBnClickedCheckLayer1(); + afx_msg void OnBnClickedCheckLayer2(); + afx_msg void OnBnClickedCheckLayer3(); + afx_msg void OnBnClickedCheckLayer4(); + + // Layer selection for audience + afx_msg void OnSelchangeComboLayerSelect(); + + //Agora Event handler + afx_msg LRESULT OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDUserJoined(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDUserOffline(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDRemoteVideoStats(WPARAM wParam, LPARAM lParam); + +private: + //set control text from config. + void InitCtrlText(); + //create all video window to save m_videoWnds. + void CreateAllVideoWnds(); + //render local video from SDK local capture. + void RenderLocalVideo(); + //stop local video capture from SDK + void StopLocalVideo(); + void ResetVideoView(); + + // Update UI based on role selection + void UpdateUIForRole(); + // Get the number of checked layers + int GetCheckedLayerCount(); + + IRtcEngine* m_rtcEngine = nullptr; + CSimulcastRtcEngineEventHandler m_eventHandler; + bool m_joinChannel = false; + bool m_initialize = false; + //video wnd + CAGVideoWnd m_videoWnds[VIDEO_COUNT_SIMULCAST]; + std::list m_lstUids; + int m_uid = 0; + +public: + CComboBox m_cmbRole; + CStatic m_staRole; + CEdit m_edtChannelName; + CButton m_btnJoinChannel; + CListBox m_lstInfo; + CStatic m_videoArea; + CStatic m_staChannelName; + + // Broadcaster layer checkboxes + CButton m_chkLayer1; + CButton m_chkLayer2; + CButton m_chkLayer3; + CButton m_chkLayer4; + CStatic m_staLayerTitle; + + // Audience layer selection + CComboBox m_cmbLayerSelect; + CStatic m_staLayerSelect; + + virtual BOOL PreTranslateMessage(MSG* pMsg); + + void ConfigureSimulcast(); +}; \ No newline at end of file diff --git a/windows/APIExample/APIExample/Advanced/SpatialAudio/CAgoraSpatialAudioDlg.cpp b/windows/APIExample/APIExample/Advanced/SpatialAudio/CAgoraSpatialAudioDlg.cpp index 032a14c11..df0cebd49 100755 --- a/windows/APIExample/APIExample/Advanced/SpatialAudio/CAgoraSpatialAudioDlg.cpp +++ b/windows/APIExample/APIExample/Advanced/SpatialAudio/CAgoraSpatialAudioDlg.cpp @@ -208,7 +208,7 @@ void CAgoraSpatialAudioDlg::UnInitAgora() //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp b/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp index ab9108ead..f0988e077 100644 --- a/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp +++ b/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp @@ -445,7 +445,7 @@ void CTransparentBgDlg::UnInitAgora() if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Basic/JoinChannelVideoByToken/CJoinChannelVideoByTokenDlg.cpp b/windows/APIExample/APIExample/Basic/JoinChannelVideoByToken/CJoinChannelVideoByTokenDlg.cpp index 82adb0a60..b0c70d0a9 100644 --- a/windows/APIExample/APIExample/Basic/JoinChannelVideoByToken/CJoinChannelVideoByTokenDlg.cpp +++ b/windows/APIExample/APIExample/Basic/JoinChannelVideoByToken/CJoinChannelVideoByTokenDlg.cpp @@ -12,7 +12,7 @@ is called without a user ID specified. The server will automatically assign one parameters: channel:channel name. - uid: user ID。If the UID is specified in the joinChannel, that ID is returned here; + uid: user ID锟斤拷If the UID is specified in the joinChannel, that ID is returned here; Otherwise, use the ID automatically assigned by the Agora server. elapsed: The Time from the joinChannel until this event occurred (ms). */ @@ -34,7 +34,7 @@ void CJoinChannelVideoByTokenRtcEngineEventHandler::onJoinChannelSuccess(const c parameters: uid: remote user/anchor ID for newly added channel. elapsed: The joinChannel is called from the local user to the delay triggered - by the callback(ms). + by the callback锟斤拷ms). */ void CJoinChannelVideoByTokenRtcEngineEventHandler::onUserJoined(uid_t uid, int elapsed) { if (m_hMsgHanlder) { @@ -310,7 +310,7 @@ void CJoinChannelVideoByTokenDlg::UnInitAgora() m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("disableVideo")); //release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Basic/LiveBroadcasting/CLiveBroadcastingDlg.cpp b/windows/APIExample/APIExample/Basic/LiveBroadcasting/CLiveBroadcastingDlg.cpp index cb20d2fd9..bdbad998b 100755 --- a/windows/APIExample/APIExample/Basic/LiveBroadcasting/CLiveBroadcastingDlg.cpp +++ b/windows/APIExample/APIExample/Basic/LiveBroadcasting/CLiveBroadcastingDlg.cpp @@ -394,7 +394,7 @@ void CLiveBroadcastingDlg::UnInitAgora() // release engine. if (m_initialize) { - m_rtcEngine->release(true); + m_rtcEngine->release(nullptr); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine")); } m_rtcEngine = NULL; diff --git a/windows/APIExample/APIExample/Language.h b/windows/APIExample/APIExample/Language.h index 11455b740..098007be8 100755 --- a/windows/APIExample/APIExample/Language.h +++ b/windows/APIExample/APIExample/Language.h @@ -48,6 +48,7 @@ extern wchar_t advancedAudioVolume[INFO_LEN]; extern wchar_t advancedReportInCall[INFO_LEN]; extern wchar_t advancedRegionConn[INFO_LEN]; extern wchar_t advancedCrossChannel[INFO_LEN]; +extern wchar_t advancedSimulcast[INFO_LEN]; extern wchar_t advancedMediaEncrypt[INFO_LEN]; @@ -338,6 +339,7 @@ extern wchar_t SpatialAudioMoveInfo[INFO_LEN]; extern wchar_t SpatialAudioPrepareInfo[INFO_LEN]; // beauty extern wchar_t beautyFace[INFO_LEN]; +extern wchar_t beautyFace2[INFO_LEN]; extern wchar_t mediaRecorderStartRecording[INFO_LEN]; extern wchar_t mediaRecorderStopRecording[INFO_LEN]; @@ -365,4 +367,6 @@ extern wchar_t CrossChannelCrossChannelList[INFO_LEN]; extern wchar_t CrossChannelCtrlToken[INFO_LEN]; extern wchar_t CrossChannelCtrlUid[INFO_LEN]; +extern wchar_t Multipath[INFO_LEN]; + diff --git a/windows/APIExample/APIExample/en.ini b/windows/APIExample/APIExample/en.ini index 1648e9c0e..79fac7c2d 100755 --- a/windows/APIExample/APIExample/en.ini +++ b/windows/APIExample/APIExample/en.ini @@ -319,4 +319,6 @@ CrossChannel.Ctrl.AddChannel = AddChannel CrossChannel.Ctrl.RemoveChannel = RemoveChannel CrossChannel.Ctrl.StartMediaRelay = StartMediaRelay CrossChannel.Ctrl.StopMediaRelay = StopMediaRelay -CrossChannel.Ctrl.UpdateMediaRelay = UpdateMediaRelay \ No newline at end of file + +Advanced.Multipath=Multipath +Advanced.Simulcast=Simulcast \ No newline at end of file diff --git a/windows/APIExample/APIExample/resource.h b/windows/APIExample/APIExample/resource.h index 038d0364e..d58a677dc 100755 --- a/windows/APIExample/APIExample/resource.h +++ b/windows/APIExample/APIExample/resource.h @@ -1,6 +1,6 @@ //{{NO_DEPENDENCIES}} -// Microsoft Visual C++ 生成的包含文件。 -// 供 APIExample.rc 使用 +// Microsoft Visual C++ 锟斤拷锟缴的帮拷锟斤拷锟侥硷拷锟斤拷 +// 锟斤拷 APIExample.rc 使锟斤拷 // #define IDM_ABOUTBOX 0x0010 #define IDD_ABOUTBOX 100 @@ -54,6 +54,8 @@ #define IDD_DIALOG_BEAUTY1 178 #define IDD_DIALOG_VIDEO_ENHANCE 178 #define IDD_DIALOG_BEAUTY_EX 178 +#define IDD_DIALOG_MULTIPATH 179 +#define IDD_DIALOG_SIMULCAST 180 #define IDC_BUTTON_FAQ 1000 #define IDC_BUTTON_DOCUMENT2 1001 #define IDC_BUTTON_DOCUMENT_WEBSITE 1001 @@ -461,14 +463,28 @@ #define IDC_COMBO_LIP_COLOR 1181 #define IDC_COMBO_FACE_SHAPE_AREA 1182 #define IDC_SLIDER__SHAPE_AREA_INTENSITY 1183 +#define IDC_LIST_INFO_MULTIPATH 1184 +#define IDC_COMBO_MULTIPATH_MODE 1185 +#define IDC_STATIC_MULTIPATH_MODE 1186 +#define IDC_LIST_INFO_SIMULCAST 1187 +#define IDC_CHECK_LAYER1 1188 +#define IDC_CHECK_LAYER2 1189 +#define IDC_CHECK_LAYER3 1190 +#define IDC_CHECK_LAYER4 1191 +#define IDC_COMBO_LAYER_SELECT 1192 +#define IDC_STATIC_LAYER_TITLE 1193 +#define IDC_STATIC_LAYER_SELECT 1194 +#define IDC_BASEWND_VIDEO_SIMULCAST 1195 +#define IDC_CHECK_ENABLE_MULTIPATH 1196 +#define IDC_STATIC_ENABLE_MULTIPATH 1197 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 181 +#define _APS_NEXT_RESOURCE_VALUE 182 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1169 +#define _APS_NEXT_CONTROL_VALUE 1198 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/windows/APIExample/APIExample/stdafx.cpp b/windows/APIExample/APIExample/stdafx.cpp index 80205d351..9f7c894fa 100755 --- a/windows/APIExample/APIExample/stdafx.cpp +++ b/windows/APIExample/APIExample/stdafx.cpp @@ -304,6 +304,7 @@ wchar_t liveBraodcastingFristFrameTipContent[INFO_LEN] = { 0 }; wchar_t liveBraodcastingVideoImage[INFO_LEN] = { 0 }; wchar_t beautyFace[INFO_LEN] = { 0 }; +wchar_t beautyFace2[INFO_LEN] = { 0 }; wchar_t SpatialAudio[INFO_LEN] = { 0 }; wchar_t SpatialAudioInitInfo[INFO_LEN] = { 0 }; wchar_t SpatialAudioMoveInfo[INFO_LEN] = { 0 }; @@ -337,6 +338,9 @@ wchar_t CrossChannelCrossChannelList[INFO_LEN] = { 0 }; wchar_t CrossChannelCtrlToken[INFO_LEN] = { 0 }; wchar_t CrossChannelCtrlUid[INFO_LEN] = { 0 }; +wchar_t Multipath[INFO_LEN] = { 0 }; +wchar_t advancedSimulcast[INFO_LEN] = { 0 }; + std::string cs2utf8(CString str) { char szBuf[2 * MAX_PATH] = { 0 }; @@ -506,6 +510,7 @@ void InitKeyInfomation() _tcscpy_s(advancedReportInCall, INFO_LEN, Str(_T("Advanced.ReportInCall"))); _tcscpy_s(advancedRegionConn, INFO_LEN, Str(_T("Advanced.RegionConn"))); _tcscpy_s(advancedCrossChannel, INFO_LEN, Str(_T("Advanced.CrossChannel"))); + _tcscpy_s(advancedSimulcast, INFO_LEN, Str(_T("Advanced.Simulcast"))); _tcscpy_s(advancedMediaEncrypt, INFO_LEN, Str(_T("Advanced.MediaEncrypt"))); //agora @@ -772,7 +777,7 @@ void InitKeyInfomation() _tcscpy_s(liveBraodcastingVideoImage, INFO_LEN, Str(_T("LiveBroadcasting.Ctrl.VideoImage"))); _tcscpy_s(beautyFace, INFO_LEN, Str(_T("Beauty.Face"))); - + _tcscpy_s(beautyFace2, INFO_LEN, Str(_T("Beauty.Face.2"))); _tcscpy_s(beautyAudioCtrlParam1, INFO_LEN, Str(_T("BeautyAudio.Ctrl.Param1"))); _tcscpy_s(beautyAudioCtrlParam2, INFO_LEN, Str(_T("BeautyAudio.Ctrl.Param2"))); @@ -811,7 +816,7 @@ void InitKeyInfomation() _tcscpy_s(CrossChannelStopMediaRelay, INFO_LEN, Str(_T("CrossChannel.Ctrl.StopMediaRelay"))); _tcscpy_s(CrossChannelUpdateMediaRelay, INFO_LEN, Str(_T("CrossChannel.Ctrl.UpdateMediaRelay"))); - + _tcscpy_s(Multipath, INFO_LEN, Str(_T("Advanced.Multipath"))); /* _tcscpy_s(, INFO_LEN, Str(_T(""))); _tcscpy_s(, INFO_LEN, Str(_T(""))); _tcscpy_s(, INFO_LEN, Str(_T(""))); diff --git a/windows/APIExample/APIExample/stdafx.h b/windows/APIExample/APIExample/stdafx.h index b444442a1..6cb17ba91 100644 --- a/windows/APIExample/APIExample/stdafx.h +++ b/windows/APIExample/APIExample/stdafx.h @@ -122,7 +122,8 @@ using namespace agora::media; #define EID_ON_FACE_INFO 0x00000039 #define EID_ON_RECV_AUDIO_METADATA 0x0000003A - +#define EID_MULTIPATH_STATS 0x0000003B +#define EID_NETWORK_TYPE_CHANGED 0x0000003C typedef struct _tagRtmpStreamStateChanged { char* url; diff --git a/windows/APIExample/APIExample/zh-cn.ini b/windows/APIExample/APIExample/zh-cn.ini index ad54593b4..cf35016df 100755 --- a/windows/APIExample/APIExample/zh-cn.ini +++ b/windows/APIExample/APIExample/zh-cn.ini @@ -279,6 +279,7 @@ LiveBroadcasting.Ctrl.FristFrameTip = LiveBroadcasting.Ctrl.FristFrameTipContent = 开启后无法关闭,并且需要主辅两端都开启时才生效。是否打开? LiveBroadcasting.Ctrl.VideoImage = 垫片 Beauty.Face = 美颜 +Beauty.Face.2 = 美颜2.0 SpatialAudio=空间音频 @@ -308,4 +309,7 @@ CrossChannel.Ctrl.AddChannel = CrossChannel.Ctrl.RemoveChannel = 移除频道 CrossChannel.Ctrl.StartMediaRelay = 开始媒体连接 CrossChannel.Ctrl.StopMediaRelay = 断开媒体连接 -CrossChannel.Ctrl.UpdateMediaRelay = 更新媒体连接 \ No newline at end of file +CrossChannel.Ctrl.UpdateMediaRelay = 更新媒体连接 + +Advanced.Multipath=网络传输高级功能 +Advanced.Simulcast=同源多流 \ No newline at end of file