p2p传输实时视频流

HYP2P是好游科技开发的p2p sdk,利用nat穿透的原理实现p2p打洞,主要用于实时音视频的传输。使用时可以配置成tcp模式或udp模式,tcp模式会自动帮您解决丢包、乱序、重传问题。中转模式则是基于tcp实现的。您可以灵活的自定义通信双方的协议,HYP2P不会解析您的业务数据。

下面通过两个程序配合演示p2p传输实时视频流,一个作为播放端的A,另一个是提供rtsp视频服务的B,A和B分别运行于不同的内网机器上。程序启动时A和B都是连接p2p服务器,打洞成功后,A直接从B获取rtsp视频流,并由vlc播放。

rtsp协议本身支持用udp或tcp传输实际的视频流,由于HYP2P的底层是由udp实现的,因此为了简单,我们这里配置vlc播放器使用tcp模式: 运行VLC media player后 ,选择工具—偏好设置—输入/编解码器。在最下面的live555流传输中选择 RTP over RTSP (TCP), 如下图:

下面先看程序A的代码,以下示例代码在windows下用vc2017或以上编译并执行。


#include "stdafx.h"
#include "p2papi.h"

int g_nlocalport=0;
int DEVICE_ID   = 1000;
int g_nP2PSetUp = 0;

class CP2PHoleSink : public IP2PSessionSink
{
public:
    CP2PHoleSink()
    {
    }
    ~CP2PHoleSink()
    {
    }

    virtual void onServerConnected(int session, int state)
    {
        p2p_login_server(session, DEVICE_ID);
    }

    virtual void  onLoginServer(int session, int state)
    {
        //13是要连接的设备ID
        p2p_connect_peer(session,13);
    }

    virtual void onHoleState(int session, int state)
    {        
        g_nP2PSetUp =state;        
    }

    virtual void onRecvServerData(int cmd, int subcmd, const unsigned char * pDataBuffer, int wDataSize)
    {
    }

    virtual void onRecvP2PData(int session,int channel, const unsigned char * pDataBuffer, int wDataSize)
    {
    }

    virtual void onChannelState(int session,int state)
    {
    }

    virtual bool OnSocketCommand(int wMain, int sub, const void* pData, int nLen)
    {
        return true;
    }

    virtual void onProxyStarted(int session, int port)
    {
    }
};

int main(int argc, char* argv[])
{
    int frame_index = 0;
    int64_t start_time = 0;
    if (argc >= 2)
        DEVICE_ID = atoi(argv[1]);

    printf("my deviceid = %d\n", DEVICE_ID);

    p2p_engine_init("43.142.138.68",20000,"d:/p2p.log");//"192.168.3.166"
    
    int sessionID = p2p_get_free_session();
    CP2PHoleSink sink;
    p2p_set_sink(sessionID,&sink);

    g_nlocalport = 49999;
    p2p_start_proxy(sessionID, g_nlocalport,1);

    int64_t p2puid = DEVICE_ID | 0x1000000000000000;
    p2p_connect_server(sessionID, p2puid, "");
    printf("local server port=%d\n", g_nlocalport);

    while (1)
    {
        SleepEx(10,TRUE);
    }

    p2p_stop_proxy(sessionID);
    p2p_engine_destroy();

    return 0;
}

与上一篇发送hello wold字符串的示例相比只是多了下面两行代码

    g_nlocalport = 49999;
    p2p_start_proxy(sessionID, g_nlocalport,1);

表示视频流将被获取到本机的49999端口上,vlc只需要将播放地址设置为:rtsp://127.0.0.1:49999/video/test.264,既可播放B程序提供的视频流。

接着再看程序B的代码,以下示例代码在windows下用vc2017或以上编译并执行。


#include "stdafx.h"
#include "p2papi.h"
#include "livemedia.h"

int DEVICE_ID   = 13;
int g_nP2PSetUp = 0;

class CP2PHoleSink : public IP2PSessionSink
{
public:
    CP2PHoleSink()
    {

    }
    ~CP2PHoleSink()
    {

    }

    virtual void onServerConnected(int session, int state)
    {
        p2p_login_server(session, DEVICE_ID);
    }

    virtual void  onLoginServer(int session, int state)
    {

    }

    virtual void onHoleState(int session, int state)
    {        
        g_nP2PSetUp=state;    
    }

    virtual void onRecvServerData(int cmd, int subcmd, const unsigned char * pDataBuffer, int wDataSize)
    {

    }

    virtual void onRecvP2PData(int session,int channel, const unsigned char * pDataBuffer, int wDataSize)
    {

    }

    virtual void onChannelState(int session,int state)
    {

    }

    virtual bool OnSocketCommand(int wMain, int sub, const void* pData, int nLen)
    {
        return true;
    }

    virtual void onProxyStarted(int session, int port)
    {


    }
};

int main(int argc, char* argv[])
{
    int frame_index = 0;
    int64_t start_time = 0;
    if (argc >= 2)
        DEVICE_ID = atoi(argv[1]);

    p2p_engine_init("43.142.138.68",20000,"d:\p2pserver.log");//"192.168.3.166"

    DWORD last_update_time = GetTickCount();
    DWORD last_framenum_update = last_update_time;
    DWORD nFrameNum = 0;
    int initVal = 0;

    printf("my deviceid = %d\n", DEVICE_ID );
    int sessionID = p2p_get_free_session();

    CP2PHoleSink sink;
    p2p_set_sink(sessionID,&sink);
    
    //设备授权ID和密钥:4294967390,49uozeazd9
    //此授权ID与p2p_login_server中的设备ID不同
    p2p_connect_server(sessionID, 4294967390, "49uozeazd9");
    
    int serviceport = start_rtsp_server();
    p2p_set_device_port(sessionID, serviceport);

    while (initVal == 0)
    {
        rtsp_server_update();
        SleepEx(10,TRUE);
    }
    
    p2p_stop_proxy(sessionID);
    stop_rtsp_server();
    p2p_engine_destroy();
    return 0;
}

与上一篇发送hello wold字符串的示例相比只是多了下面一行代码

//serviceport参数是提供视频流的端口号    
p2p_set_device_port(sessionID, serviceport);

此示例程序B中  livemedia.h 是实现rtsp功能库的头文件,里面定义了三个函数:start_rtsp_server,rtsp_server_update, stop_rtsp_server。

这三个函数本身与p2p功能不相关,只是实现rtsp视频流服务器的功能。

下面是vcl播放p2p视频的截屏:

以上通过两个控制台程序展示了使用 p2p传输rtsp视频的例子, 如有任何凝问,加我qq:390090739

测试时必须先运行B程序,再运行A程序,然后运行vcl media player,打开vcl后,选择 媒体—打开网络串流—网络,输入地址rtsp://127.0.0.1:49999/video/test.264,然后点“播放”按扭。 

完整的示例代码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值