腾讯LVB流推送SDK 测试样例
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<string> | |
#include<exception> | |
#include<windows.h> | |
#include<avsdk/av_sdk.h> | |
using namespace tencent::av; | |
using namespace std; | |
#define ENABLE_CONSOLE | |
AVContext* context = NULL; | |
#define Log OutputDebugStringA | |
HINSTANCE g_hInst; | |
HWND g_hWnd; | |
//------------------------------------------------------ | |
// Called every time the application receives a message | |
//------------------------------------------------------ | |
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) | |
{ | |
PAINTSTRUCT ps; | |
HDC hdc; | |
RECT rc; | |
UINT width; | |
UINT height; | |
switch( message ) | |
{ | |
default: | |
return DefWindowProc( hWnd, message, wParam, lParam ); | |
} | |
return 0; | |
} | |
HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow) | |
{ | |
// Register class | |
WNDCLASSEX wcex; | |
wcex.cbSize = sizeof( WNDCLASSEX ); | |
wcex.style = CS_HREDRAW | CS_VREDRAW; | |
wcex.lpfnWndProc = WndProc; | |
wcex.cbClsExtra = 0; | |
wcex.cbWndExtra = 0; | |
wcex.hInstance = hInstance; | |
wcex.hIcon = LoadIcon( hInstance, NULL ); | |
wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); | |
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); | |
wcex.lpszMenuName = NULL; | |
wcex.lpszClassName = "aMazingWndClass"; | |
wcex.hIconSm = LoadIcon( wcex.hInstance, NULL ); | |
if( !RegisterClassEx( &wcex ) ) | |
return E_FAIL; | |
// Create window | |
g_hInst = hInstance; | |
RECT rc = { 0, 0, 640, 480 }; | |
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); | |
g_hWnd = CreateWindowA( "aMazingWndClass", "testtesttest", WS_OVERLAPPEDWINDOW, | |
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, | |
NULL ); | |
if( !g_hWnd ) | |
return E_FAIL; | |
ShowWindow( g_hWnd, true ); | |
return S_OK; | |
} | |
class Handler:public AVRoomMulti::Delegate { | |
public: | |
/** | |
* 音频控制器 | |
*/ | |
AVAudioCtrl *m_pAudCtrl; | |
/** | |
* 视频控制器 | |
*/ | |
AVVideoCtrl *m_pVidCtrl; | |
/** | |
* 音频管理 | |
**/ | |
AVDeviceMgr *m_pAudMgr; | |
/** | |
* 视频管理 | |
*/ | |
AVDeviceMgr *m_pVidMgr; | |
/** | |
* 麦克风列表 | |
*/ | |
std::vector<std::pair<std::string/*id*/, std::string/*name*/> > m_micList; | |
/** | |
* 成员列表 | |
*/ | |
std::vector<std::pair<std::string/*id*/, std::string/*name*/> > m_playerList; | |
/** | |
* 相机列表 | |
*/ | |
std::vector<std::pair<std::string/*id*/, std::string/*name*/> > m_cameraList; | |
/** | |
* 当前选中相机的名称 | |
*/ | |
std::string m_selectedCameraId; | |
// 登录成功! | |
void OnStartContextComplete(int result) { | |
if (result != AV_OK) | |
{ | |
cout << "Error On Start!" << endl; | |
return; | |
} | |
m_pAudCtrl = dynamic_cast<AVAudioCtrl*>(context->GetAudioCtrl()); | |
m_pVidCtrl = dynamic_cast<AVVideoCtrl*>(context->GetVideoCtrl()); | |
if(!m_pAudCtrl || !m_pVidCtrl) | |
{ | |
cout << "Error On Start!" << endl; | |
return; | |
} | |
cout << "Start Succeed!" << endl; | |
} | |
static void OnStartContextCompleteCallback(int32 result, void *pCustomData) { | |
((Handler*)pCustomData)->OnStartContextComplete(result); | |
} | |
static void OnVideoDeviceOperationCallback(AVDeviceMgr *pVidMgr, AVDevice::DeviceOperation oper, const std::string &deviceId, int retCode, void *pCustomData) { | |
if(!pVidMgr)return; | |
AVDevice *pDev = pVidMgr->GetDeviceById(deviceId); | |
if(!pDev)return; | |
if(pDev->GetType() == DEVICE_CAMERA) | |
{ | |
if(retCode == AV_OK) | |
{ | |
Handler* pSdkWrapper = (Handler*)pCustomData; | |
// pSdkWrapper->SetDefaultCameraState(oper == AVDevice::DEVICE_OPERATION_OPEN); | |
} | |
cout << "摄像机运行中" << endl; | |
// ::PostMessage(GetMainHWnd(), WM_ON_CAMERA_OPERATION, (WPARAM)retCode, oper); | |
} | |
//else if(pDev->GetType() == DEVICE_REMOTE_VIDEO) | |
//{ | |
// //TODO | |
//} | |
else if(pDev->GetType() == DEVICE_LOCAL_SCREEN_VIDEO) | |
{ | |
if(retCode == AV_OK) | |
{ | |
Handler *pSdkWrapper = (Handler*)pCustomData; | |
//pSdkWrapper->SetDefaultScreenShareSendState(oper == AVDevice::DEVICE_OPERATION_OPEN); | |
} | |
//::PostMessage(GetMainHWnd(), WM_ON_SCREEN_SHARE_SEND_OPERATION, (WPARAM)retCode, oper); | |
} | |
//else if(pDev->GetType() == DEVICE_REMOTE_SCREEN_VIDEO) | |
//{ | |
// //TODO | |
//} | |
//else | |
//{ | |
// //TODO | |
//} | |
} | |
static void OnVideoDeviceChangeCallback(AVDeviceMgr *pVidMgr, void *pCustomData) | |
{ | |
if(!pVidMgr)return; | |
Handler *pSdkWrapper = (Handler*)pCustomData; | |
int retCode = AV_OK; | |
retCode = pSdkWrapper->GetCameraList(pSdkWrapper->m_cameraList); | |
if (pSdkWrapper->m_selectedCameraId == "") | |
{ | |
pSdkWrapper->m_selectedCameraId = retCode == AV_OK ? pSdkWrapper->m_cameraList[0].first : ""; | |
} | |
//::PostMessage(GetMainHWnd(), WM_ON_CAMERA_CHANGE, NULL, NULL); | |
} | |
virtual void OnEnterRoomComplete(int result) { | |
m_pAudMgr = static_cast<AVDeviceMgr*>(context->GetAudioDeviceMgr()); | |
m_pVidMgr = static_cast<AVDeviceMgr*>(context->GetVideoDeviceMgr()); | |
m_pVidMgr->SetDeviceOperationCallback(OnVideoDeviceOperationCallback, this); | |
m_pVidMgr->SetDeviceChangeCallback(OnVideoDeviceChangeCallback, this); | |
//创建房间后,设置远程视频回调 | |
AVRemoteVideoDevice *pVideoDevice = (AVRemoteVideoDevice*)m_pVidMgr->GetDeviceById(DEVICE_REMOTE_VIDEO); | |
if (pVideoDevice) | |
{ | |
//视频渲染前,先设定渲染画面大小和颜色格式。这些参数设置只影响到渲染,不影响到编解码。 | |
m_pVidMgr->SelectOutputDevice(DEVICE_REMOTE_VIDEO, true); | |
// | |
//AVSupportVideoPreview::PreviewParam m_remoteVideoParam; | |
//pVideoDevice->SetPreviewParam(m_remoteVideoParam.device_id, m_remoteVideoParam.width, m_remoteVideoParam.height, m_remoteVideoParam.color_format); | |
//pVideoDevice->SetPreviewCallback(&Handler::OnRemoteVideo, this); | |
} | |
//AVRemoteScreenVideoDevice *pScreenShareRecvDevice = (AVRemoteScreenVideoDevice*)m_pVidMgr->GetDeviceById(DEVICE_REMOTE_SCREEN_VIDEO); | |
//if (pScreenShareRecvDevice) | |
//{ | |
// //视频渲染前,先设定渲染画面大小和颜色格式。这些参数设置只影响到渲染,不影响到编解码。 | |
// m_pVidMgr->SelectOutputDevice(DEVICE_REMOTE_SCREEN_VIDEO, true); | |
// pScreenShareRecvDevice->SetPreviewParam(m_screenRecvParam.device_id, m_screenRecvParam.width, m_screenRecvParam.height, m_screenRecvParam.color_format); | |
// pScreenShareRecvDevice->SetPreviewCallback(&SdkWrapper::OnRemoteVideo, this); | |
//} | |
/* | |
int retCode = AV_OK; | |
retCode = GetCameraList(m_cameraList); | |
if (m_selectedCameraId == "") | |
{ | |
m_selectedCameraId = retCode == AV_OK ? m_cameraList[0].first : ""; | |
} | |
m_pAudMgr->SetDeviceOperationCallback(OnAudioDeviceOperationCallback, this); | |
m_pAudMgr->SetDeviceDetectNotify(OnAudioDeviveDetectNotify,this); | |
retCode = GetMicList(m_micList); | |
m_selectedMicId = retCode == AV_OK ? m_micList[0].first : ""; | |
retCode = GetPlayerList(m_playerList); | |
m_selectedPlayerId = retCode == AV_OK ? m_playerList[0].first : ""; | |
m_pRoom = dynamic_cast<AVRoomMulti*>(m_pContext->GetRoom()); | |
if(!m_pRoom) | |
{ | |
::PostMessage(GetMainHWnd(), WM_ON_ENTER_ROOM, (WPARAM)AV_ERR_FAILED, 0); | |
return; | |
} | |
::PostMessage(GetMainHWnd(), WM_ON_ENTER_ROOM, (WPARAM)result, 0); | |
*/ | |
} | |
virtual void OnExitRoomComplete() { | |
std::cout << "Exit Room! " << std::endl; } | |
virtual void OnRoomDisconnect(int32 reason) { | |
std::cout << "Leave! " << reason << std::endl; | |
} | |
virtual void OnEndpointsUpdateInfo(AVRoomMulti::EndpointEventId event_id, std::vector<std::string> identifier_list){} | |
virtual void OnPrivilegeDiffNotify(int32 privilege){} | |
virtual void OnSemiAutoRecvCameraVideo(std::vector<std::string> identifier_list){} | |
virtual void OnCameraSettingNotify(int32 width, int32 height, int32 fps){} | |
/** | |
* 拿到摄像头设备列表 | |
*/ | |
virtual int GetCameraList(std::vector<std::pair<std::string/*id*/, std::string/*name*/> > &cameraList) | |
{ | |
if(!context || !m_pAudCtrl || !m_pVidCtrl || !m_pVidMgr) return AV_ERR_FAILED; | |
AVDevice **ppCameraList = NULL; | |
int cameraCount = m_pVidMgr->GetDeviceByType(DEVICE_CAMERA, &ppCameraList); | |
if(ppCameraList == NULL || cameraCount == 0) | |
{ | |
return AV_ERR_DEVICE_NOT_EXIST; | |
} | |
for(int i = 0; i < cameraCount; i++) | |
{ | |
std::pair<std::string/*id*/, std::string/*name*/> camera; | |
camera.first = ppCameraList[i]->GetId(); | |
camera.second = ppCameraList[i]->GetInfo().name; | |
cameraList.push_back(camera); | |
} | |
if(ppCameraList)delete []ppCameraList;//业务侧负责释放这个数组。 | |
return AV_OK; | |
} | |
}; | |
static Handler* fuckingHandler = new Handler; | |
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) | |
{ | |
#ifdef ENABLE_CONSOLE | |
AllocConsole(); | |
FILE * m_new_stdout_file = nullptr; | |
freopen_s(&m_new_stdout_file, "CONOUT$", "w+t", stdout); | |
#endif | |
UNREFERENCED_PARAMETER( hPrevInstance ); | |
UNREFERENCED_PARAMETER( lpCmdLine ); | |
if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) | |
return 0; | |
HMODULE m_hMoude = ::LoadLibraryA("qavsdk.dll"); | |
// 拿到版本号 | |
auto getVersionProc = (PROC_AVAPI_GetVersion)::GetProcAddress(m_hMoude, "AVAPI_GetVersion"); | |
cout << "当前版本号是" << getVersionProc() << endl; | |
// 登录 | |
// 开启崩溃报告 | |
auto enableCrashReportProc = (PROC_AVAPI_EnableCrashReport)::GetProcAddress(m_hMoude, "AVAPI_EnableCrashReport"); | |
enableCrashReportProc(true, false); | |
// 创建context | |
auto createContext = (PROC_AVAPI_CreateContext)::GetProcAddress(m_hMoude, "AVAPI_CreateContext"); | |
context = (AVContext*)(*createContext)(); | |
// 设置对应context属性 | |
context->SetSpearEngineMode(SPEAR_EGINE_MODE_CUSTOM); //开启Spear是SPEAR_EGINE_MODE_WEBCLOUD | |
// 初始化参数 | |
AVContext::StartParam startParam; | |
startParam.sdk_app_id = 1104062745; | |
startParam.account_type = "107"; | |
startParam.app_id_at3rd = "1104062745"; | |
startParam.identifier = "antimoron_123123123"; // 瞎jb测试 | |
// 据说是start context | |
//context->Start(param, &SdkWrapper::OnStartContextCompleteCallback, this); | |
int startError = context->Start(startParam, &Handler::OnStartContextCompleteCallback, fuckingHandler); | |
if(startError != AV_OK) { | |
return 0; | |
} | |
Sleep(5000); | |
// 选择一个房间 | |
AVRoomMulti::EnterParam enterRoomParam; | |
string relationId = "123123"; // 拿到群组id (relationId) | |
string avControlRole = ""; // 流控制角色名 | |
enterRoomParam.relation_id = atoi(relationId.c_str()); | |
enterRoomParam.control_role = avControlRole; // | |
/*if( 0 != m_btnCheckHasVideoSendAuth.GetCheck() && | |
0 != m_btnCheckHasAudioSendAuth.GetCheck() && | |
0 != m_btnCheckHasVideoRevAuth.GetCheck() && | |
0 != m_btnCheckHasAudioRevAuth.GetCheck() )*/ | |
{ | |
enterRoomParam.auth_bits = AUTH_BITS_DEFAULT; //权限位;默认值是拥有所有权限。TODO:请业务侧填根据自己的情况填上权限位。 | |
} | |
/*else | |
{ | |
enterRoomParam.auth_bits = AUTH_BITS_CREATE_ROOM | AUTH_BITS_JOIN_ROOM | AUTH_BITS_RECV_SCREEN_VIDEO; | |
if( 0 != m_btnCheckHasVideoSendAuth.GetCheck() ) | |
enterRoomParam.auth_bits |= AUTH_BITS_SEND_CAMERA_VIDEO; | |
if( 0 != m_btnCheckHasAudioSendAuth.GetCheck() ) | |
enterRoomParam.auth_bits |= AUTH_BITS_SEND_AUDIO; | |
if( 0 != m_btnCheckHasVideoRevAuth.GetCheck() ) | |
enterRoomParam.auth_bits |= AUTH_BITS_RECV_CAMERA_VIDEO; | |
if( 0 != m_btnCheckHasAudioRevAuth.GetCheck() ) | |
enterRoomParam.auth_bits |= AUTH_BITS_RECV_AUDIO; | |
}*/ | |
//设置音视频编解码参数。如果需要设定特定的音视频参数,请在创建房间前设置好。 | |
//主播场景,支持设置自定义音视频参数。 | |
// 做一层校验 | |
if((startParam.account_type == "107" && startParam.app_id_at3rd == "1104062745" && startParam.sdk_app_id == 1104062745)) { | |
//音频场景策略;有三种取值:实时通信场景,直播场景中的主播人员,直播场景中的听众;TODO:请业务侧根据自己的情况填这个值。 | |
enterRoomParam.audio_category = AUDIO_CATEGORY_MEDIA_PLAY_AND_RECORD;//直播场景 | |
} else { | |
//音频场景策略;有三种取值:实时通信场景,直播场景中的主播人员,直播场景中的听众;TODO:请业务侧根据自己的情况填这个值。 | |
enterRoomParam.audio_category = AUDIO_CATEGORY_VOICECHAT;//实时通信场景 | |
} | |
// 这个控制是否音视频服务器自动创建房间 | |
bool isAutoCreateSDKRoom = true; | |
enterRoomParam.create_room = isAutoCreateSDKRoom; | |
if (isAutoCreateSDKRoom) { | |
enterRoomParam.video_recv_mode = VIDEO_RECV_MODE_SEMI_AUTO_RECV_CAMERA_VIDEO; | |
} else { | |
enterRoomParam.video_recv_mode = VIDEO_RECV_MODE_MANUAL; | |
} | |
int enterRoomResponse = context->EnterRoom(fuckingHandler, enterRoomParam); | |
cout << enterRoomResponse << endl; | |
if(enterRoomResponse != AV_OK) { | |
cout << "进入房间失败" << endl; | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment