2

c# WPF程序接入声网dll详细步骤及测试demo

声网是视频及音频聊天工具,由于官网只提供C++DLL,无法直接用到WPF程序中。为了方便开发者使用,我是对声网DLL进行进一步封装,封装成自己的接口,同时方便c#调用。

第一步,将agora_rtc_sdk.lib封装成自己的DLL:

先导入agora_rtc_sdk.lib以及确定头文件pch.h

#ifndef _PCH_H_
#define _PCH_H_


#include <windows.h>
#include <IAgoraRtcEngine.h>
#include <IAgoraMediaEngine.h>
#include <string>


#define WINDOWS
#define EXPORT

#include <malloc.h>
#ifdef WINDOWS
#ifdef EXPORT
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API __declspec(dllimport)
#endif
#else
#include <stdlib.h>

#ifdef EXPORT
#define EXPORT_API __attribute__((visibility ("default")))
#else
#endif

#endif
#pragma comment(lib, "agora_rtc_sdk.lib")

#endif // !_PCH_H_

其次定义声网所需要的事件声明

#include"pch.h"

using namespace agora::rtc;

class CAGEngineEventHandler :
    public IRtcEngineEventHandler
{
public:
    CAGEngineEventHandler(void);
    ~CAGEngineEventHandler(void);

    void SetMsgReceiver(HWND hWnd = NULL);
    HWND GetMsgReceiver() {return m_hMainWnd;};

    virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed);
    virtual void onRejoinChannelSuccess(const char* channel, uid_t uid, int elapsed);
    virtual void onWarning(int warn, const char* msg);
    virtual void onError(int err, const char* msg);
    virtual void onAudioQuality(uid_t uid, int quality, unsigned short delay, unsigned short lost);
    virtual void onAudioVolumeIndication(const AudioVolumeInfo* speakers, unsigned int speakerNumber, int totalVolume);
    
    virtual void onLeaveChannel(const RtcStats& stat);
    virtual void onRtcStats(const RtcStats& stat);
    virtual void onMediaEngineEvent(int evt);

    virtual void onAudioDeviceStateChanged(const char* deviceId, int deviceType, int deviceState);
    virtual void onVideoDeviceStateChanged(const char* deviceId, int deviceType, int deviceState);

    virtual void onLastmileQuality(int quality);
    virtual void onFirstLocalVideoFrame(int width, int height, int elapsed);
    virtual void onFirstRemoteVideoDecoded(uid_t uid, int width, int height, int elapsed);
    virtual void onFirstRemoteVideoFrame(uid_t uid, int width, int height, int elapsed);
    virtual void onUserJoined(uid_t uid, int elapsed);
    virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason);
    virtual void onUserMuteAudio(uid_t uid, bool muted);
    virtual void onUserMuteVideo(uid_t uid, bool muted);
    virtual void onApiCallExecuted(const char* api, int error);

    virtual void onStreamMessage(uid_t uid, int streamId, const char* data, size_t length);
    
    virtual void onLocalVideoStats(const LocalVideoStats& stats);
    virtual void onRemoteVideoStats(const RemoteVideoStats& stats);
    virtual void onCameraReady();
    virtual void onVideoStopped();
    virtual void onConnectionLost();
    virtual void onConnectionInterrupted();

    virtual void onUserEnableVideo(uid_t uid, bool enabled);

    virtual void onStartRecordingService(int error);
    virtual void onStopRecordingService(int error);
    virtual void onRefreshRecordingServiceStatus(int status);
private:
    HWND        m_hMainWnd;
};

最后封装成自己的接口
将声网的createAgoraRtcEngine和initialize封装成一个接口Init

EXPORT_API int Init() // 定义你需要使用的函数
{
    RtcEngineContext m_RtcEngineContext;

    m_RtcEngineContext.eventHandler = &m_EngineEventHandler;
    m_RtcEngineContext.appId = "输入appid";

    m_lpAgoraEngine = (IRtcEngine *)createAgoraRtcEngine();

    int nRet=m_lpAgoraEngine->initialize(m_RtcEngineContext);

    
    return nRet;

}

封装JoinChannel

EXPORT_API int JoinChannel(const char* ChannelName, HWND wnd)
{
    int nRet = 0;

    VideoCanvas vc;

    vc.uid = 0;
    vc.view = wnd;
    vc.renderMode = RENDER_MODE_TYPE::RENDER_MODE_FIT;

    int m_nVideoSolution = 100;
    m_lpAgoraEngine->setChannelProfile(CHANNEL_PROFILE_COMMUNICATION);
    m_lpAgoraEngine->setVideoProfile((VIDEO_PROFILE_TYPE)m_nVideoSolution, true);

    m_lpAgoraEngine->enableVideo();
    m_lpAgoraEngine->setupLocalVideo(vc);
    m_lpAgoraEngine->startPreview();
    

    nRet = m_lpAgoraEngine->joinChannel(NULL, ChannelName, NULL, 0);

    m_EngineEventHandler.SetMsgReceiver(wnd);

    return nRet;
}

第二步,创建WPF程序及调用dll

导入dll

        [DllImport("VideoCommunicationDll.dll", EntryPoint = "Init", CharSet = CharSet.Auto, CallingConvention = 
         CallingConvention.Cdecl)]
        internal static extern int Init();

        [DllImport("VideoCommunicationDll.dll", EntryPoint = "JoinChannel", CharSet = CharSet.Auto, CallingConvention 
         = CallingConvention.Cdecl)]
        internal static extern int JoinChannel(string channel,IntPtr wnd);

        [DllImport("VideoCommunicationDll.dll", EntryPoint = "LeaverChannel", CharSet = CharSet.Auto, 
        CallingConvention = CallingConvention.Cdecl)]
        internal static extern int LeaverChannel();

使用dll

            int a = Init(); 
            IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(image)).Handle;
            int b = JoinChannel("ssss", hwnd);

实现效果图

clipboard.png

工程源码请私信作者


生活如此艰难
4 声望13 粉丝