diff --git a/windows/APIExample/APIExample/APIExample.rc b/windows/APIExample/APIExample/APIExample.rc index fb7ec45bc..7621d33ff 100755 --- a/windows/APIExample/APIExample/APIExample.rc +++ b/windows/APIExample/APIExample/APIExample.rc @@ -752,6 +752,20 @@ BEGIN EDITTEXT IDC_EDIT_TOKEN,69,363,128,29,ES_AUTOHSCROLL END +IDD_DIALOG_TRANSPARENT_BG DIALOGEX 0, 0, 632, 400 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Channel Name",IDC_STATIC_CHANNELNAME,136,360,48,8 + EDITTEXT IDC_EDIT_CHANNELNAME,216,358,172,13,ES_AUTOHSCROLL + PUSHBUTTON "JoinChannel",IDC_BUTTON_JOINCHANNEL,420,358,75,14 + LTEXT "",IDC_STATIC_DETAIL,23,370,412,27 + LTEXT "",IDC_STATIC_VIDEO,0,0,419,147 + LTEXT "",IDC_STATIC_VIDEO_RIGHT,233,175,176,136 + LTEXT "",IDC_STATIC_VIDEO_LEFT,2,173,171,136 + LISTBOX IDC_LIST_INFO_BROADCASTING,491,0,139,312,LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP +END + ///////////////////////////////////////////////////////////////////////////// // @@ -907,6 +921,14 @@ BEGIN HORZGUIDE, 163 END + IDD_DIALOG_VOLUME, DIALOG + BEGIN + END + + IDD_DIALOG_PEPORT_IN_CALL, DIALOG + BEGIN + END + IDD_DIALOG_REGIONAL_CONNECTION, DIALOG BEGIN END @@ -1048,6 +1070,12 @@ BEGIN HORZGUIDE, 348 HORZGUIDE, 363 END + + IDD_DIALOG_TRANSPARENT_BG, DIALOG + BEGIN + RIGHTMARGIN, 630 + BOTTOMMARGIN, 397 + END END #endif // APSTUDIO_INVOKED @@ -1187,6 +1215,11 @@ BEGIN 0 END +IDD_DIALOG_TRANSPARENT_BG AFX_DIALOG_LAYOUT +BEGIN + 0 +END + ///////////////////////////////////////////////////////////////////////////// // diff --git a/windows/APIExample/APIExample/APIExample.vcxproj b/windows/APIExample/APIExample/APIExample.vcxproj index ae9d15a06..ca7174446 100644 --- a/windows/APIExample/APIExample/APIExample.vcxproj +++ b/windows/APIExample/APIExample/APIExample.vcxproj @@ -94,7 +94,7 @@ Level3 Disabled false - WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions); + WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(solutionDir)ThirdParty\libFFmpeg\include;$(solutionDir)ThirdParty\Boost;$(SolutionDir)sdk\high_level_api\include;$(solutionDir)ThirdParty\libYUV;$(ProjectDir) MultiThreadedDLL @@ -121,7 +121,8 @@ if exist zh-cn.ini (copy zh-cn.ini $(SolutionDir)$(Configuration)) if exist en.ini (copy en.ini $(SolutionDir)$(Configuration)) copy $(SolutionDir)APIExample\Advanced\LocalVideoTranscoding\agora.png $(SolutionDir)$(Configuration) copy $(SolutionDir)APIExample\Advanced\LocalVideoTranscoding\agora.jpg $(SolutionDir)$(Configuration) -if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Configuration)) +if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Configuration)) +if exist $(SolutionDir)APIExample\res\yuvj_full_range_alpha_1280_540_left.mp4 (copy $(SolutionDir)APIExample\res\yuvj_full_range_alpha_1280_540_left.mp4 $(SolutionDir)$(Configuration)) @@ -167,6 +168,7 @@ if exist en.ini (copy en.ini $(SolutionDir)$(Platform)\$(Configuration)) copy $(SolutionDir)APIExample\Advanced\LocalVideoTranscoding\agora.png $(SolutionDir)$(Platform)\$(Configuration) copy $(SolutionDir)APIExample\Advanced\LocalVideoTranscoding\agora.jpg $(SolutionDir)$(Platform)\$(Configuration) if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)$(Configuration)) +if exist $(SolutionDir)APIExample\res\yuvj_full_range_alpha_1280_540_left.mp4 (copy $(SolutionDir)APIExample\res\yuvj_full_range_alpha_1280_540_left.mp4 $(SolutionDir)$(Configuration)) @@ -267,6 +269,7 @@ if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)\$(Configuration)) + @@ -295,6 +298,7 @@ if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)\$(Configuration)) + @@ -319,6 +323,7 @@ if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)\$(Configuration)) + @@ -347,6 +352,7 @@ if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)\$(Configuration)) + @@ -395,6 +401,7 @@ if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)\$(Configuration)) Document + @@ -418,6 +425,7 @@ if exist sample.yuv (copy sample.yuv $(SolutionDir)$(Platform)\$(Configuration)) Document + diff --git a/windows/APIExample/APIExample/APIExample.vcxproj.filters b/windows/APIExample/APIExample/APIExample.vcxproj.filters index de1e3f9ea..a16906e88 100644 --- a/windows/APIExample/APIExample/APIExample.vcxproj.filters +++ b/windows/APIExample/APIExample/APIExample.vcxproj.filters @@ -112,6 +112,9 @@ {ed782797-3b06-44a9-8894-6b9d93d0dfea} + + {2a74c488-9982-4577-8594-8320c71beb6d} + @@ -264,6 +267,12 @@ Advanced\Metadata + + Advanced\TransparentBg + + + Header Files + @@ -404,6 +413,12 @@ Advanced\Metadata + + Advanced\TransparentBg + + + Source Files + @@ -420,6 +435,9 @@ Resource Files + + Resource Files + @@ -442,6 +460,9 @@ Resource Files + + Resource Files + diff --git a/windows/APIExample/APIExample/APIExampleDlg.cpp b/windows/APIExample/APIExample/APIExampleDlg.cpp index 7281c0795..959268f1f 100755 --- a/windows/APIExample/APIExample/APIExampleDlg.cpp +++ b/windows/APIExample/APIExample/APIExampleDlg.cpp @@ -255,6 +255,9 @@ void CAPIExampleDlg::InitSceneDialog() m_pMultiChannelDlg->Create(CAgoraMultiChannelDlg::IDD); m_pMultiChannelDlg->MoveWindow(&rcWnd); + //transparent bg + m_vecAdvanced.push_back(TransparentBackground); + //inject m_pRtmpInjectDlg = new CAgoraRtmpInjectionDlg(&m_staMainArea); m_pRtmpInjectDlg->Create(CAgoraRtmpInjectionDlg::IDD); @@ -382,6 +385,12 @@ void CAPIExampleDlg::InitSceneDialog() m_pMultiVideoSourceTracks = new MultiVideoSourceTracks(&m_staMainArea); m_pMultiVideoSourceTracks->Create(MultiVideoSourceTracks::IDD); m_pMultiVideoSourceTracks->MoveWindow(&rcWnd); + + // transparent bg + m_TransparentDlg = new CTransparentBgDlg(&m_staMainArea); + m_TransparentDlg->Create(CTransparentBgDlg::IDD); + m_TransparentDlg->MoveWindow(&rcWnd); + } void CAPIExampleDlg::InitSceneList() @@ -604,6 +613,10 @@ void CAPIExampleDlg::CreateScene(CTreeCtrl& treeScene, CString selectedText) m_pmediaRecorderDlg->InitAgora(); m_pmediaRecorderDlg->ShowWindow(SW_SHOW); } + else if (selectedText.Compare(TransparentBackground) == 0) { + m_TransparentDlg->InitAgora(); + m_TransparentDlg->ShowWindow(SW_SHOW); + } //Sleep(500); } @@ -709,6 +722,10 @@ void CAPIExampleDlg::ReleaseScene(CTreeCtrl& treeScene, HTREEITEM& hSelectItem) m_pmediaRecorderDlg->UnInitAgora(); m_pmediaRecorderDlg->ShowWindow(SW_HIDE); } + else if (str.Compare(TransparentBackground) == 0) { + m_TransparentDlg->UnInitAgora(); + m_TransparentDlg->ShowWindow(SW_HIDE); + } //Sleep(500); } diff --git a/windows/APIExample/APIExample/APIExampleDlg.h b/windows/APIExample/APIExample/APIExampleDlg.h index 12c9bd6bb..295ed85c9 100755 --- a/windows/APIExample/APIExample/APIExampleDlg.h +++ b/windows/APIExample/APIExample/APIExampleDlg.h @@ -33,6 +33,7 @@ #include "Advanced/PushExternalVideoYUV/PushExternalVideoYUV.h" #include "Advanced/MultiVideoSourceTracks/MultiVideoSourceTracks.h" #include "Advanced/FaceCapture/CAgoraFaceCaptureDlg.h" +#include "Advanced/TransparentBg/TransparentBgDialog.h" #include #include #include @@ -108,6 +109,7 @@ class CAPIExampleDlg : public CDialogEx MultiVideoSourceTracks *m_pMultiVideoSourceTracks = nullptr; CAgoraFaceCaptureDlg *m_pAgoraFaceCaptureDlg = nullptr; CDlgBeauty * m_pDlgBeauty = nullptr; + CTransparentBgDlg* m_TransparentDlg = nullptr; CString m_preSelectedItemText = _T(""); std::vector m_vecBasic, m_vecAdvanced; std::mutex m_mutex; diff --git a/windows/APIExample/APIExample/AbstractMediaPlayerSourceObserver.cpp b/windows/APIExample/APIExample/AbstractMediaPlayerSourceObserver.cpp new file mode 100644 index 000000000..2cfadad76 --- /dev/null +++ b/windows/APIExample/APIExample/AbstractMediaPlayerSourceObserver.cpp @@ -0,0 +1,45 @@ +#include "AbstractMediaPlayerSourceObserver.h" + +void AbstractMediaPlayerSourceObserver::onPlayerSourceStateChanged(media::base::MEDIA_PLAYER_STATE state, media::base::MEDIA_PLAYER_REASON reason) +{ +} + +void AbstractMediaPlayerSourceObserver::onPositionChanged(int64_t positionMs, int64_t timestampMs) +{ +} + +void AbstractMediaPlayerSourceObserver::onPlayerEvent(media::base::MEDIA_PLAYER_EVENT eventCode, int64_t elapsedTime, const char *message) +{ +} + +void AbstractMediaPlayerSourceObserver::onMetaData(const void *data, int length) +{ +} + +void AbstractMediaPlayerSourceObserver::onPlayBufferUpdated(int64_t playCachedBuffer) +{ +} + +void AbstractMediaPlayerSourceObserver::onPreloadEvent(const char *src, media::base::PLAYER_PRELOAD_EVENT event) +{ +} + +void AbstractMediaPlayerSourceObserver::onCompleted() +{ +} + +void AbstractMediaPlayerSourceObserver::onAgoraCDNTokenWillExpire() +{ +} + +void AbstractMediaPlayerSourceObserver::onPlayerSrcInfoChanged(const media::base::SrcInfo &from, const media::base::SrcInfo &to) +{ +} + +void AbstractMediaPlayerSourceObserver::onPlayerInfoUpdated(const media::base::PlayerUpdatedInfo &info) +{ +} + +void AbstractMediaPlayerSourceObserver::onAudioVolumeIndication(int volume) +{ +} diff --git a/windows/APIExample/APIExample/AbstractMediaPlayerSourceObserver.h b/windows/APIExample/APIExample/AbstractMediaPlayerSourceObserver.h new file mode 100644 index 000000000..362b10e5e --- /dev/null +++ b/windows/APIExample/APIExample/AbstractMediaPlayerSourceObserver.h @@ -0,0 +1,27 @@ +#pragma once +#include "stdafx.h" +#include +#include +#include + +using namespace agora; +using namespace agora::rtc; +class AbstractMediaPlayerSourceObserver : + public IMediaPlayerSourceObserver +{ +public: + + virtual void onPlayerSourceStateChanged(media::base::MEDIA_PLAYER_STATE state, media::base::MEDIA_PLAYER_REASON reason) override; + void onPositionChanged(int64_t positionMs, int64_t timestampMs) override; + void onPlayerEvent(media::base::MEDIA_PLAYER_EVENT eventCode, int64_t elapsedTime, const char* message) override; + void onMetaData(const void* data, int length) override; + void onPlayBufferUpdated(int64_t playCachedBuffer) override; + void onPreloadEvent(const char* src, media::base::PLAYER_PRELOAD_EVENT event) override; + void onCompleted() override; + void onAgoraCDNTokenWillExpire() override; + void onPlayerSrcInfoChanged(const media::base::SrcInfo& from, const media::base::SrcInfo& to) override; + void onPlayerInfoUpdated(const media::base::PlayerUpdatedInfo& info) override; + void onAudioVolumeIndication(int volume) override; + +}; + diff --git a/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp b/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp new file mode 100644 index 000000000..f3f7cb8d2 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.cpp @@ -0,0 +1,687 @@ +#include "stdafx.h" +#include "APIExample.h" +#include "TransparentBgDialog.h" + +void CTransparentBgEventHandler::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 CTransparentBgEventHandler::onUserJoined(uid_t uid, int elapsed) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_USER_JOINED), (WPARAM)uid, (LPARAM)elapsed); + } +} + +void CTransparentBgEventHandler::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 CTransparentBgEventHandler::onLeaveChannel(const RtcStats &stats) +{ + if (m_hMsgHanlder) + { + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LEAVE_CHANNEL), 0, 0); + } +} + +void CTransparentBgEventHandler::onLocalVideoStats(VIDEO_SOURCE_TYPE source, const LocalVideoStats &stats) +{ + if (m_hMsgHanlder && report) + { + LocalVideoStats *s = new LocalVideoStats; + *s = stats; + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LOCAL_VIDEO_STATS), (WPARAM)s, 0); + } +} + +IMPLEMENT_DYNAMIC(CTransparentBgDlg, CDialogEx) + +CTransparentBgDlg::CTransparentBgDlg(CWnd *pParent /*=nullptr*/) + : CDialogEx(IDD_DIALOG_TRANSPARENT_BG, pParent) +{ +} + +CTransparentBgDlg::~CTransparentBgDlg() +{ +} + +void CTransparentBgDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_STATIC_CHANNELNAME, m_staticChannelName); + DDX_Control(pDX, IDC_BUTTON_JOINCHANNEL, m_bnJoinChannel); + DDX_Control(pDX, IDC_EDIT_CHANNELNAME, m_editChannel); + DDX_Control(pDX, IDC_STATIC_VIDEO, m_staticVideo); + DDX_Control(pDX, IDC_STATIC_VIDEO_LEFT, m_staticVideoLeft); + DDX_Control(pDX, IDC_STATIC_VIDEO_RIGHT, m_staticVideoRight); + DDX_Control(pDX, IDC_LIST_INFO_BROADCASTING, m_listInfo); +} + +BEGIN_MESSAGE_MAP(CTransparentBgDlg, CDialogEx) + +ON_MESSAGE(WM_MSGID(EID_JOINCHANNEL_SUCCESS), &CTransparentBgDlg::OnEIDJoinChannelSuccess) +ON_MESSAGE(WM_MSGID(EID_ERROR), &CTransparentBgDlg::OnEIDError) +ON_MESSAGE(WM_MSGID(EID_LEAVE_CHANNEL), &CTransparentBgDlg::OnEIDLeaveChannel) +ON_MESSAGE(WM_MSGID(EID_USER_JOINED), &CTransparentBgDlg::OnEIDUserJoined) +ON_MESSAGE(WM_MSGID(EID_USER_OFFLINE), &CTransparentBgDlg::OnEIDUserOffline) + +ON_MESSAGE(WM_MSGID(EID_LOCAL_AUDIO_STATS), &CTransparentBgDlg::onEIDLocalAudioStats) +ON_MESSAGE(WM_MSGID(EID_REMOTE_AUDIO_STATS), &CTransparentBgDlg::onEIDRemoteAudioStats) +ON_MESSAGE(WM_MSGID(EID_LOCAL_VIDEO_STATS), &CTransparentBgDlg::onEIDLocalVideoStats) +ON_MESSAGE(WM_MSGID(EID_REMOTE_VIDEO_STATS), &CTransparentBgDlg::onEIDRemoteVideoStats) + +ON_WM_SHOWWINDOW() + +ON_BN_CLICKED(IDC_BUTTON_JOINCHANNEL, &CTransparentBgDlg::OnBnClickedButtonJoinchannel) +ON_WM_SHOWWINDOW() +END_MESSAGE_MAP() + +BOOL CTransparentBgDlg::_IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) +{ + typedef LONG(WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW *, ULONG, ULONGLONG); + static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = NULL; + if (RtlVerifyVersionInfoFn == NULL) + if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll")) + RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress( + ntdllModule, "RtlVerifyVersionInfo"); + if (RtlVerifyVersionInfoFn == NULL) + return FALSE; + RTL_OSVERSIONINFOEXW versionInfo = {}; + ULONGLONG conditionMask = 0; + versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); + versionInfo.dwMajorVersion = major; + versionInfo.dwMinorVersion = minor; + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + return (RtlVerifyVersionInfoFn(&versionInfo, + VER_MAJORVERSION | VER_MINORVERSION, + conditionMask) == 0) + ? TRUE + : FALSE; +} + +void CTransparentBgDlg::enable_alpha_composition(void *hwnd) +{ + if (!_IsWindowsVistaOrGreater()) + { + return; + } + BOOL composition; + if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition) + return; + BOOL opaque; + DWORD color; + if (_IsWindows8OrGreater() || + (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque)) + { + HRGN region = ::CreateRectRgn(0, 0, -1, -1); + DWM_BLURBEHIND bb = {}; + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = region; + bb.fEnable = TRUE; + ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); + ::DeleteObject(region); + } + else + { + DWM_BLURBEHIND bb = {}; + bb.dwFlags = DWM_BB_ENABLE; + ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); + } +} + +// CTransparentBgDlg message handlers +BOOL CTransparentBgDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + CString className("TransparentWindowClass"); + WNDCLASS wndcls = {}; + HINSTANCE hInst = AfxGetInstanceHandle(); + if (!(::GetClassInfo(hInst, className, &wndcls))) + { + wndcls.style = CS_HREDRAW | CS_VREDRAW; + wndcls.lpfnWndProc = ::DefWindowProc; + wndcls.cbClsExtra = wndcls.cbWndExtra = 0; + wndcls.hInstance = hInst; + wndcls.hIcon = NULL; + wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW); + wndcls.hbrBackground = NULL; + wndcls.lpszMenuName = NULL; + wndcls.lpszClassName = className; + if (AfxRegisterClass(&wndcls)) + { + hWnd = CreateWindowEx( + 0, // 扩展窗口样式 + className, // 窗口类名 + _T("透明窗口"), // 窗口标题 + WS_OVERLAPPEDWINDOW & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX & ~WS_SYSMENU, // 窗口样式 + CW_USEDEFAULT, CW_USEDEFAULT, // 窗口位置 + 800, 600, // 窗口大小 + this->GetSafeHwnd(), // 父窗口句柄 + NULL, // 菜单句柄 + AfxGetInstanceHandle(), // 应用程序实例句柄 + NULL // 窗口创建数据 + ); + if (hWnd) + { + enable_alpha_composition(hWnd); + } + } + } + return TRUE; +} + +void CTransparentBgDlg::ShowTransparentWindow() +{ + if (hWnd) + { + ::ShowWindow(hWnd, SW_SHOW); // 显示窗口 + UpdateWindow(); // 更新窗口 + } +} +void CTransparentBgDlg::HideTransparentWindow() +{ + if (hWnd) + { + ::ShowWindow(hWnd, SW_HIDE); // 隐藏窗口 + UpdateWindow(); // 更新窗口 + } +} + +// set control text from config. +void CTransparentBgDlg::InitCtrlText() +{ + m_staticChannelName.SetWindowText(commonCtrlChannel); + m_bnJoinChannel.SetWindowText(commonCtrlJoinChannel); + m_editChannel.SetWindowText(_T("")); +} + +void CTransparentBgDlg::InvalidateVideo() +{ + m_staticVideo.Invalidate(); + m_staticVideoLeft.Invalidate(); + m_staticVideoRight.Invalidate(); +} + +int CTransparentBgDlg::JoinChannel(const char *channel) +{ + VideoEncoderConfiguration config; + config.advanceOptions.encodeAlpha = true; + m_rtcEngine->setVideoEncoderConfiguration(config); + + ChannelMediaOptions options; + options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING; + options.clientRoleType = CLIENT_ROLE_BROADCASTER; + options.autoSubscribeAudio = false; + options.autoSubscribeVideo = true; + options.publishMicrophoneTrack = false; + options.publishCameraTrack = false; + options.publishCustomVideoTrack = true; + // join channel in the engine. + int ret = m_rtcEngine->joinChannel(APP_TOKEN, channel, m_uid, options); + + return ret; +} + +int CTransparentBgDlg::LeaveChannel() +{ + if (!m_joinChannel) + { + return 0; + }; + m_rtcEngine->stopPreview(); + int ret = m_rtcEngine->leaveChannel(); + m_joinChannel = false; + m_remoteId = 0; + return ret; +} + +void CTransparentBgDlg::StartPlay() +{ + m_mediaPlayer = m_rtcEngine->createMediaPlayer(); + if (m_mediaPlayer) + { + m_mediaPlayer->setView((agora::media::base::view_t)m_staticVideo.GetSafeHwnd()); + m_mediaPlayer->setRenderMode(RENDER_MODE_FIT); + m_mediaPlayer->registerVideoFrameObserver(this); + m_mediaPlayer->registerPlayerSourceObserver(this); + MediaSource mediaSource; + CString videoUrl = GetExePath() + _T("\\yuvj_full_range_alpha_1280_540_left.mp4"); + std::string tmp = cs2utf8(videoUrl); + mediaSource.url = tmp.c_str(); + CString pathInfo; + int ret = m_mediaPlayer->openWithMediaSource(mediaSource); + CString strInfo; + strInfo.Format(_T("openWithMediaSource ret: %d"), ret); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + m_mediaPlayer->setLoopCount(-1); + } +} + +void CTransparentBgDlg::StopPlay() +{ + if (m_mediaPlayer) + { + m_mediaPlayer->stop(); + } +} +void CTransparentBgDlg::onFrame(const VideoFrame *frame) +{ + if (m_rtcEngine) + { + + // 创建ExternalVideoFrame对象 + agora::media::base::ExternalVideoFrame externalFrame; + externalFrame.alphaStitchMode = ALPHA_STITCH_LEFT; + externalFrame.type = agora::media::base::ExternalVideoFrame::VIDEO_BUFFER_TYPE::VIDEO_BUFFER_RAW_DATA; + externalFrame.format = agora::media::base::VIDEO_PIXEL_I420; + externalFrame.stride = frame->width; + externalFrame.height = frame->height; + externalFrame.timestamp = m_rtcEngine->getCurrentMonotonicTimeInMs(); + + int bufferSize = frame->yStride * frame->height + frame->uStride * (frame->height >> 1) + frame->vStride * (frame->height >> 1); + externalFrame.buffer = new uint8_t[bufferSize]; + memcpy(externalFrame.buffer, frame->yBuffer, frame->yStride * frame->height); + memcpy((uint8_t *)externalFrame.buffer + frame->yStride * frame->height, frame->uBuffer, frame->uStride * (frame->height >> 1)); + memcpy((uint8_t *)externalFrame.buffer + frame->yStride * frame->height + frame->uStride * (frame->height >> 1), frame->vBuffer, frame->vStride * (frame->height / 2)); + mediaEngine->pushVideoFrame(&externalFrame); + // 释放缓冲区 + delete[] externalFrame.buffer; + + // CString strInfo; + // strInfo.Format(_T("height ret: %d"), frame->height); + // m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + } +} + +void CTransparentBgDlg::onPlayerSourceStateChanged(media::base::MEDIA_PLAYER_STATE state, media::base::MEDIA_PLAYER_REASON reason) +{ + CString strState; + CString strError; + switch (state) + { + case agora::media::base::PLAYER_STATE_OPEN_COMPLETED: + strState = _T("PLAYER_STATE_OPEN_COMPLETED"); + m_mediaPlayer->play(); + break; + case agora::media::base::PLAYER_STATE_OPENING: + strState = _T("PLAYER_STATE_OPENING"); + break; + case agora::media::base::PLAYER_STATE_IDLE: + strState = _T("PLAYER_STATE_IDLE"); + break; + case agora::media::base::PLAYER_STATE_PLAYING: + strState = _T("PLAYER_STATE_PLAYING"); + break; + case agora::media::base::PLAYER_STATE_PLAYBACK_COMPLETED: + strState = _T("PLAYER_STATE_PLAYBACK_COMPLETED"); + break; + case agora::media::base::PLAYER_STATE_PLAYBACK_ALL_LOOPS_COMPLETED: + strState = _T("PLAYER_STATE_PLAYBACK_ALL_LOOPS_COMPLETED"); + break; + case agora::media::base::PLAYER_STATE_PAUSED: + strState = _T("PLAYER_STATE_PAUSED"); + break; + case agora::media::base::PLAYER_STATE_STOPPED: + strState = _T("PLAYER_STATE_STOPPED"); + break; + case agora::media::base::PLAYER_STATE_FAILED: + strState = _T("PLAYER_STATE_FAILED"); + m_mediaPlayer->stop(); + break; + default: + strState = _T("PLAYER_STATE_UNKNOWN"); + break; + } + switch (reason) + { + case agora::media::base::PLAYER_REASON_URL_NOT_FOUND: + strError = _T("PLAYER_ERROR_URL_NOT_FOUND"); + break; + case agora::media::base::PLAYER_REASON_NONE: + strError = _T("PLAYER_ERROR_NONE"); + break; + case agora::media::base::PLAYER_REASON_CODEC_NOT_SUPPORTED: + strError = _T("PLAYER_ERROR_NONE"); + break; + case agora::media::base::PLAYER_REASON_INVALID_ARGUMENTS: + strError = _T("PLAYER_ERROR_INVALID_ARGUMENTS"); + break; + case agora::media::base::PLAYER_REASON_SRC_BUFFER_UNDERFLOW: + strError = _T("PLAY_ERROR_SRC_BUFFER_UNDERFLOW"); + break; + case agora::media::base::PLAYER_REASON_INTERNAL: + strError = _T("PLAYER_ERROR_INTERNAL"); + break; + case agora::media::base::PLAYER_REASON_INVALID_STATE: + strError = _T("PLAYER_ERROR_INVALID_STATE"); + break; + case agora::media::base::PLAYER_REASON_NO_RESOURCE: + strError = _T("PLAYER_ERROR_NO_RESOURCE"); + break; + case agora::media::base::PLAYER_REASON_OBJ_NOT_INITIALIZED: + strError = _T("PLAYER_ERROR_OBJ_NOT_INITIALIZED"); + break; + case agora::media::base::PLAYER_REASON_INVALID_CONNECTION_STATE: + strError = _T("PLAYER_ERROR_INVALID_CONNECTION_STATE"); + break; + case agora::media::base::PLAYER_REASON_UNKNOWN_STREAM_TYPE: + strError = _T("PLAYER_ERROR_UNKNOWN_STREAM_TYPE"); + break; + case agora::media::base::PLAYER_REASON_VIDEO_RENDER_FAILED: + strError = _T("PLAYER_ERROR_VIDEO_RENDER_FAILED"); + break; + } + CString strInfo; + strInfo.Format(_T("sta:%s,\nerr:%s"), strState, strError); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); +} + +// Initialize the Agora SDK +bool CTransparentBgDlg::InitAgora() +{ + // create Agora RTC engine + m_rtcEngine = createAgoraRtcEngine(); + if (!m_rtcEngine) + { + m_listInfo.InsertString(m_listInfo.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; + // 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_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + return false; + } + else + { + m_initialize = true; + m_listInfo.InsertString(m_listInfo.GetCount(), _T("createAgoraRtcEngine success")); + + mediaEngine.queryInterface(m_rtcEngine, agora::rtc::AGORA_IID_MEDIA_ENGINE); + agora::base::AParameter apm(m_rtcEngine); + mediaEngine->setExternalVideoSource(true, true); + } + m_rtcEngine->enableVideo(); + m_rtcEngine->enableAudio(); + return true; +} + +// UnInitialize the Agora SDK +void CTransparentBgDlg::UnInitAgora() +{ + if (m_rtcEngine) + { + if (m_joinChannel) + LeaveChannel(); + // m_rtcEngine->stopPreview(); + m_rtcEngine->disableVideo(); + if (m_mediaPlayer) + { + // m_mediaPlayer->registerPlayerSourceObserver(nullptr); + m_mediaPlayer->Release(); + m_mediaPlayer = nullptr; + } + + if (m_initialize) + { + m_rtcEngine->release(true); + } + m_rtcEngine = NULL; + + // if (hWnd) + // { + + // ::DestroyWindow(hWnd); + // hWnd = NULL; + // } + HideTransparentWindow(); + } +} + +LRESULT CTransparentBgDlg::OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam) +{ + CString strInfo; + strInfo.Format(TEXT("self join success, wParam=%u"), wParam); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + // notify parent window + ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(EID_JOINCHANNEL_SUCCESS), TRUE, 0); + return 0; +} + +LRESULT CTransparentBgDlg::OnEIDError(WPARAM wParam, LPARAM lParam) +{ + CString strInfo; + char *message = (char *)wParam; + int code = lParam; + strInfo.Format(TEXT("Error >> code=%d, message=%s"), code, message); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + delete message; + return 0; +} + +LRESULT CTransparentBgDlg::OnEIDLeaveChannel(WPARAM wParam, LPARAM lParam) +{ + CString strInfo; + strInfo.Format(TEXT("leave channel success")); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + // notify parent window + ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(EID_JOINCHANNEL_SUCCESS), FALSE, 0); + InvalidateVideo(); + return 0; +} + +LRESULT CTransparentBgDlg::OnEIDUserJoined(WPARAM wParam, LPARAM lParam) +{ + if (m_remoteId != 0) + { + m_listInfo.InsertString(m_listInfo.GetCount(), _T("user joined already")); + return 0; + } + CString strInfo; + strInfo.Format(TEXT("user %u joined"), wParam); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + uid_t remoteUid = (uid_t)wParam; + m_remoteId = remoteUid; + VideoCanvas canvas; + canvas.enableAlphaMask = true; + canvas.uid = m_remoteId; + // canvas.view = m_staticVideoRight.GetSafeHwnd(); + canvas.view = hWnd; + canvas.renderMode = media::base::RENDER_MODE_FIT; + m_rtcEngine->setupRemoteVideo(canvas); + ShowTransparentWindow(); + return 0; +} + +LRESULT CTransparentBgDlg::OnEIDUserOffline(WPARAM wParam, LPARAM lParam) +{ + uid_t remoteUid = (uid_t)wParam; + if (m_remoteId == remoteUid) + { + m_remoteId = 0; + VideoCanvas canvas; + canvas.uid = remoteUid; + canvas.view = NULL; + m_rtcEngine->setupRemoteVideo(canvas); + HideTransparentWindow(); + CString strInfo; + strInfo.Format(TEXT("%u offline, reason:%d"), remoteUid, lParam); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + } + InvalidateVideo(); + return 0; +} + +BOOL CTransparentBgDlg::PreTranslateMessage(MSG *pMsg) +{ + if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) + { + return TRUE; + } + return CDialogEx::PreTranslateMessage(pMsg); +} + +LRESULT CTransparentBgDlg::onEIDLocalAudioStats(WPARAM wParam, LPARAM lParam) +{ + LocalAudioStats *stats = (LocalAudioStats *)wParam; + + CString strInfo = _T("===onLocalAudioStats==="); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + strInfo.Format(_T("numChannels:%u"), stats->numChannels); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("sentSampleRate:%u"), stats->sentSampleRate); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + return 0; +} + +LRESULT CTransparentBgDlg::onEIDRemoteAudioStats(WPARAM wParam, LPARAM lParam) +{ + RemoteAudioStats *stats = (RemoteAudioStats *)wParam; + + CString strInfo = _T("===onRemoteAudioStats==="); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + strInfo.Format(_T("uid:%u"), stats->uid); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("quality:%d"), stats->quality); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + return 0; +} + +LRESULT CTransparentBgDlg::onEIDLocalVideoStats(WPARAM wParam, LPARAM lParam) +{ + LocalVideoStats *stats = (LocalVideoStats *)wParam; + + CString strInfo = _T("===onLocalVideoStats==="); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + strInfo.Format(_T("uid:%u"), stats->uid); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("sentBitrate:%d"), stats->sentBitrate); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + strInfo.Format(_T("sentFrameRate:%d"), stats->sentFrameRate); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("encoderOutputFrameRate:%d"), stats->encoderOutputFrameRate); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + return 0; +} + +LRESULT CTransparentBgDlg::onEIDRemoteVideoStats(WPARAM wParam, LPARAM lParam) +{ + RemoteVideoStats *stats = (RemoteVideoStats *)wParam; + CString strInfo = _T("===onRemoteVideoStats==="); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("uid:%u"), stats->uid); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("delay:%d"), stats->delay); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + strInfo.Format(_T("width:%d"), stats->width); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + strInfo.Format(_T("height:%d"), stats->height); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + + strInfo.Format(_T("receivedBitrate:%d"), stats->receivedBitrate); + m_listInfo.InsertString(m_listInfo.GetCount(), strInfo); + return 0; +} + +void CTransparentBgDlg::OnBnClickedButtonJoinchannel() +{ + CString info; + if (!m_joinChannel) + { + CString strChannelName; + m_editChannel.GetWindowText(strChannelName); + if (strChannelName.IsEmpty()) + { + MessageBox(_T("频道号不能为空")); + return; + } + + VideoCanvas canvas; + canvas.mirrorMode = VIDEO_MIRROR_MODE_DISABLED; + canvas.sourceType = VIDEO_SOURCE_CUSTOM; + canvas.enableAlphaMask = true; + canvas.renderMode = media::base::RENDER_MODE_FIT; + canvas.uid = m_uid; + canvas.view = m_staticVideoLeft.GetSafeHwnd(); + m_rtcEngine->setupLocalVideo(canvas); + m_rtcEngine->startPreview(VIDEO_SOURCE_CUSTOM); + + std::string szChannelName = cs2utf8(strChannelName); + int ret = JoinChannel(szChannelName.c_str()); + if (ret == 0) + { + m_joinChannel = true; + m_bnJoinChannel.SetWindowText(commonCtrlLeaveChannel); + + StartPlay(); + } + else + { + const char *des = getAgoraSdkErrorDescription(ret); + info.Format(TEXT("join channel failed >> code=%d, des=%s"), ret, utf82cs(std::string(des))); + m_listInfo.InsertString(m_listInfo.GetCount(), info); + } + } + else + { + int ret = LeaveChannel(); + HideTransparentWindow(); + if (0 == ret) + { + InitCtrlText(); + InvalidateVideo(); + StopPlay(); + } + else + { + const char *des = getAgoraSdkErrorDescription(ret); + info.Format(TEXT("leave channel failed >> code=%d, des=%s"), ret, utf82cs(std::string(des))); + m_listInfo.InsertString(m_listInfo.GetCount(), info); + } + } +} + +void CTransparentBgDlg::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialogEx::OnShowWindow(bShow, nStatus); + + if (bShow) + { + m_listInfo.ResetContent(); + } + else + { + InitCtrlText(); + InvalidateVideo(); + } +} diff --git a/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.h b/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.h new file mode 100644 index 000000000..f470e59a1 --- /dev/null +++ b/windows/APIExample/APIExample/Advanced/TransparentBg/TransparentBgDialog.h @@ -0,0 +1,140 @@ +#pragma once +#include "AGVideoWnd.h" +#include +#include +#include "stdafx.h" +#include +#include +#include "AbstractMediaPlayerSourceObserver.h" +using namespace agora::media::base; + +#define _IsWindowsVistaOrGreater() \ + _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), \ + 0) // _WIN32_WINNT_VISTA +#define _IsWindows8OrGreater() \ + _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), \ + 0) // _WIN32_WINNT_WIN8 +#define _IsWindows8Point1OrGreater() \ + _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), \ + 0) // _WIN32_WINNT_WINBLUE +#define _IsWindows10OrGreater() \ + _IsWindowsVersionOrGreater( \ + HIBYTE(0x0A00), LOBYTE(0x0A00), \ + 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10 + +class CTransparentBgEventHandler : public IRtcEngineEventHandler +{ +public: + 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 onLocalAudioStats(const LocalAudioStats &stats) override + { + if (m_hMsgHanlder && report) + { + LocalAudioStats *s = new LocalAudioStats; + *s = stats; + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LOCAL_AUDIO_STATS), (WPARAM)s, 0); + } + } + virtual void onRemoteAudioStats(const RemoteAudioStats &stats) + { + if (m_hMsgHanlder && report) + { + RemoteAudioStats *s = new RemoteAudioStats; + *s = stats; + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_REMOTE_AUDIO_STATS), (WPARAM)s, 0); + } + } + virtual void onRemoteVideoStats(const RemoteVideoStats &stats) + { + if (m_hMsgHanlder && report) + { + RemoteVideoStats *s = new RemoteVideoStats; + *s = stats; + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_REMOTE_VIDEO_STATS), (WPARAM)s, 0); + } + } + virtual void onLocalVideoStats(VIDEO_SOURCE_TYPE source, const LocalVideoStats &stats) override; + virtual void onError(int err, const char *msg) + { + if (m_hMsgHanlder) + { + char *message = new char[1024]{0}; + memcpy(message, msg, strlen(msg)); + ::PostMessage(m_hMsgHanlder, WM_MSGID(EID_ERROR), (WPARAM)message, err); + } + } + +private: + HWND m_hMsgHanlder = nullptr; + bool report = true; +}; + +class CTransparentBgDlg : public CDialogEx, media::base::IVideoFrameObserver, AbstractMediaPlayerSourceObserver +{ + DECLARE_DYNAMIC(CTransparentBgDlg) + +public: + CTransparentBgDlg(CWnd *pParent = nullptr); // standard constructor + virtual ~CTransparentBgDlg(); + bool InitAgora(); + void UnInitAgora(); + void StartPlay(); + void StopPlay(); + virtual void onFrame(const VideoFrame *frame); + virtual void onPlayerSourceStateChanged(media::base::MEDIA_PLAYER_STATE state, media::base::MEDIA_PLAYER_REASON reason); + enum + { + IDD = IDD_DIALOG_TRANSPARENT_BG + }; + +protected: + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + virtual BOOL PreTranslateMessage(MSG *pMsg); + DECLARE_MESSAGE_MAP() +public: + afx_msg LRESULT OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnEIDError(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 onEIDLocalAudioStats(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT onEIDRemoteAudioStats(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT onEIDLocalVideoStats(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT onEIDRemoteVideoStats(WPARAM wParam, LPARAM lParam); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnBnClickedButtonJoinchannel(); + +private: + void InitCtrlText(); + int JoinChannel(const char *channel); + int LeaveChannel(); + void InvalidateVideo(); + static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD); + void enable_alpha_composition(void *hwnd); + void ShowTransparentWindow(); + void HideTransparentWindow(); + + CStatic m_staticChannelName; + CButton m_bnJoinChannel; + CEdit m_editChannel; + CStatic m_staticVideo; + CStatic m_staticVideoLeft; + CStatic m_staticVideoRight; + CListBox m_listInfo; + + IRtcEngine *m_rtcEngine = nullptr; + agora_refptr m_mediaPlayer = nullptr; + agora::util::AutoPtr mediaEngine; + CTransparentBgEventHandler m_eventHandler; + // agora::media::base::ExternalVideoFrame m_videoFrame; + bool m_joinChannel = false; + bool m_initialize = false; + int m_uid = 1001; + int m_remoteId = 0; + HWND hWnd = NULL; +}; diff --git a/windows/APIExample/APIExample/Language.h b/windows/APIExample/APIExample/Language.h index 7d53ff4c2..9a18d37b6 100755 --- a/windows/APIExample/APIExample/Language.h +++ b/windows/APIExample/APIExample/Language.h @@ -348,3 +348,6 @@ extern wchar_t localVideoTranscodingVirtualBg[INFO_LEN]; extern wchar_t advancedMetadataVideo[INFO_LEN]; extern wchar_t advancedMetadataAudio[INFO_LEN]; extern wchar_t advancedMetadataSend[INFO_LEN]; + +//transparent background +extern wchar_t TransparentBackground[INFO_LEN]; diff --git a/windows/APIExample/APIExample/en.ini b/windows/APIExample/APIExample/en.ini index 985283928..0fad41a7c 100755 --- a/windows/APIExample/APIExample/en.ini +++ b/windows/APIExample/APIExample/en.ini @@ -304,4 +304,6 @@ LocalVideoTranscoding.VirtualBg=TranslusionBackground Metadata.Video=Video Metadata Metadata.Audio=Audio Metadata -Metadata.Send=Send \ No newline at end of file +Metadata.Send=Send + +TransparentBackground=TransparentBackground \ No newline at end of file diff --git a/windows/APIExample/APIExample/res/yuvj_full_range_alpha_1280_540_left.mp4 b/windows/APIExample/APIExample/res/yuvj_full_range_alpha_1280_540_left.mp4 new file mode 100644 index 000000000..2e9dfbd99 Binary files /dev/null and b/windows/APIExample/APIExample/res/yuvj_full_range_alpha_1280_540_left.mp4 differ diff --git a/windows/APIExample/APIExample/resource.h b/windows/APIExample/APIExample/resource.h index 0ec5cd196..5cfaac205 100755 --- a/windows/APIExample/APIExample/resource.h +++ b/windows/APIExample/APIExample/resource.h @@ -45,6 +45,7 @@ #define IDD_DIALOG_MULTI_VIDEO_SOURCE_TRACKS 162 #define IDD_DIALOG_FACE_CAPTURE 163 #define IDD_DIALOG_JOINCHANNELVIDEOBYTOKEN 164 +#define IDD_DIALOG_TRANSPARENT_BG 165 #define IDB_BITMAP_LOCAL 168 #define IDB_BITMAP_REMOTE 170 #define IDB_BITMAP_SPEAKER 171 @@ -401,7 +402,9 @@ #define IDC_EDIT_TOKEN 1150 #define IDC_EDIT_METADATA_INFO 1150 #define IDC_STATIC_TOKEN 1151 +#define IDC_STATIC_VIDEO_LEFT 1151 #define IDC_USER_ID 1152 +#define IDC_STATIC_VIDEO_RIGHT 1152 #define IDC_EDIT_USER_ID 1153 #define IDC_BUTTON_ADD_CROSS_CHANNEL 1154 #define IDC_CROSS_CHANNEL_LIST 1155 @@ -423,9 +426,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 173 +#define _APS_NEXT_RESOURCE_VALUE 177 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1151 +#define _APS_NEXT_CONTROL_VALUE 1153 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/windows/APIExample/APIExample/stdafx.cpp b/windows/APIExample/APIExample/stdafx.cpp index b25fb9e73..8797e7223 100755 --- a/windows/APIExample/APIExample/stdafx.cpp +++ b/windows/APIExample/APIExample/stdafx.cpp @@ -5,6 +5,7 @@ #include "stdafx.h" #include "CConfig.h" + wchar_t commonGroupDoc[INFO_LEN] = { 0 }; wchar_t commonDocumentWebsite[INFO_LEN] = { 0 }; wchar_t commonFAQWebsite[INFO_LEN] = { 0 }; @@ -318,6 +319,11 @@ wchar_t advancedMetadataVideo[INFO_LEN] = { 0 }; wchar_t advancedMetadataAudio[INFO_LEN] = { 0 }; wchar_t advancedMetadataSend[INFO_LEN] = { 0 }; + +//transparent backgroud +wchar_t TransparentBackground[INFO_LEN] = { 0 }; + + std::string cs2utf8(CString str) { char szBuf[2 * MAX_PATH] = { 0 }; @@ -767,6 +773,10 @@ void InitKeyInfomation() _tcscpy_s(advancedMetadataAudio, INFO_LEN, Str(_T("Metadata.Audio"))); _tcscpy_s(advancedMetadataSend, INFO_LEN, Str(_T("Metadata.Send"))); + //transparent bg + _tcscpy_s(TransparentBackground, INFO_LEN, Str(_T("TransparentBackground"))); + + /* _tcscpy_s(, INFO_LEN, Str(_T(""))); _tcscpy_s(, INFO_LEN, Str(_T(""))); _tcscpy_s(, INFO_LEN, Str(_T(""))); diff --git a/windows/APIExample/APIExample/zh-cn.ini b/windows/APIExample/APIExample/zh-cn.ini index 9d2e80bcd..7d44135cb 100755 --- a/windows/APIExample/APIExample/zh-cn.ini +++ b/windows/APIExample/APIExample/zh-cn.ini @@ -294,4 +294,6 @@ LocalVideoTranscoding.VirtualBg=͸ Metadata.Video=ƵԪ Metadata.Audio=ƵԪ -Metadata.Send= \ No newline at end of file +Metadata.Send= + +TransparentBackground=͸ \ No newline at end of file