如何实现多路海康大华等RTSP数据转RTMP推送

一个好的转发模块,首先要低延迟!其次足够稳定灵活、有状态反馈机制、资源占用低,跨平台,最好以接口形式提供,便于第三方系统集成。

以Windows平台为例,我们的考虑的点如下

1. 拉流:通过RTSP直播播放SDK的数据回调接口,拿到音视频数据;

2. 转推:通过RTMP直播推送SDK的编码后数据输入接口,把回调上来的数据,传给RTMP直播推送模块,实现RTSP数据流到RTMP服务器的转发;

3. 录像:如果需要录像,借助RTSP直播播放SDK,拉到音视频数据后,直接存储MP4文件即可;

4. 快照:如果需要实时快照,拉流后,解码调用播放端快照接口,生成快照,因为快照涉及到video数据解码,如无必要,可不必开启,不然会额外消耗性能。

5. 拉流预览:如需预览拉流数据,只要调用播放端的播放接口,即可实现拉流数据预览;

6. 数据转AAC后转发:考虑到好多监控设备出来的音频可能是PCMA/PCMU的,如需要更通用的音频格式,可以转AAC后,在通过RTMP推送;

7. 转推RTMP实时静音:只需要在传audio数据的地方,加个判断即可;

8. 拉流速度反馈:通过RTSP播放端的实时码率反馈event,拿到实时带宽占用即可;

9. 整体网络状态反馈:考虑到有些摄像头可能会临时或异常关闭,RTMP服务器亦是,可以通过推拉流的event回调状态,查看那整体网络情况,如此界定:是拉不到流,还是推不到RTMP服务器。

系统设计架构图

?

Windows转发demo分析

大牛直播SDK的转发demo,Windows平台,对应C++ demo工程:WIN-RelaySDK-CPP-Demo,如需下载demo源码,参看 Github

1. 拉流:拉流和播放有些类似,但不需要播放(也就是说不要解码,资源消耗非常低),在做过基础的参数配置之后(对应demo里面OpenPullHandle()),设置音视频数据回调,然后调用StartPullStream()即可:

1.1 基础参数设置:

bool nt_stream_relay_wrapper::OpenPullHandle(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute)
{
	if ( pull_handle_ != NULL )
		return true;

	if ( url.empty() )
		return false;

	duration_ = 0;

	NT_HANDLE pull_handle = NULL;

	ASSERT( pull_api_ != NULL );
	if (NT_ERC_OK != pull_api_->Open(&pull_handle, render_wnd_, 0, NULL))
	{
		return false;
	}

	ASSERT(pull_handle != NULL);

	pull_api_->SetEventCallBack(pull_handle, this, &NT_Pull_SDKEventHandle);

	pull_api_->SetBuffer(pull_handle, 0);
	pull_api_->SetFastStartup(pull_handle, 1);
	pull_api_->SetRTSPTcpMode(pull_handle, is_rtsp_tcp_mode ? 1 : 0);
	pull_api_->SetMute(pull_handle, is_mute ? 1 : 0);

	if ( NT_ERC_OK != pull_api_->SetURL(pull_handle, url.c_str()) )
	{
		pull_api_->Close(pull_handle);
		pull_handle = NULL;
		return false;
	}

	if ( setting_pos_ >= 0ll )
	{
		pull_api_->SetPos(pull_handle, setting_pos_);
	}

	pull_handle_ = pull_handle;

	return true;
}

1.2 设置音视频数据回调:

	pull_api_->SetPullStreamVideoDataCallBack(pull_handle_, this, &SP_SDKPullStreamVideoDataHandle);

	pull_api_->SetPullStreamAudioDataCallBack(pull_handle_, this, &SP_SDKPullStreamAudioDataHandle);

1.3 开始拉流:

	auto ret = pull_api_->StartPullStream(pull_handle_);
	if ( NT_ERC_OK != ret )
	{
		if ( !is_playing_ )
		{
			pull_api_->Close(pull_handle_);
			pull_handle_ = NULL;
		}

		return false;
	}

拉流整体代码如下:

bool nt_stream_relay_wrapper::StartPull(const std::string& url, bool is_rtsp_tcp_mode, bool is_transcode_aac)
{
	if ( is_pulling_ )
		return false;

	if ( !OpenPullHandle(url, is_rtsp_tcp_mode) )
		return false;

	pull_api_->SetPullStreamVideoDataCallBack(pull_handle_, this, &SP_SDKPullStreamVideoDataHandle);

	pull_api_->SetPullStreamAudioDataCallBack(pull_handle_, this, &SP_SDKPullStreamAudioDataHandle);

	pull_api_->SetPullStreamAudioTranscodeAAC(pull_handle_, is_transcode_aac? 1: 0);

	auto ret = pull_api_->StartPullStream(pull_handle_);
	if ( NT_ERC_OK != ret )
	{
		if ( !is_playing_ )
		{
			pull_api_->Close(pull_handle_);
			pull_handle_ = NULL;
		}

		return false;
	}

	is_pulling_ = true;

	return true;
}

2. 停止拉流:

停止拉流流程比较简单,先判断是否在拉流状态,如果拉流,调用StopPullStream() 即可,如没有预览画面,调用Close()接口关闭拉流实例。

void nt_stream_relay_wrapper::StopPull()
{
	if ( !is_pulling_ )
		return;

	pull_api_->StopPullStream(pull_handle_);

	if ( !is_playing_ )
	{
		pull_api_->Close(pull_handle_);
		pull_handle_ = NULL;
	}

	is_pulling_ = false;
}

3. 拉流端预览:

拉流端预览,说白了就是播放拉流数据,流程比较简单,demo调用如下,如不需要播放声音,调用SetMute(),实时打开/关闭即可:

bool nt_stream_relay_wrapper::StartPlay(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute)
{
	if ( is_playing_ )
		return false;

	if ( !OpenPullHandle(url, is_rtsp_tcp_mode, is_mute) )
		return false;

	pull_api_->SetMute(pull_handle_, is_mute ? 1 : 0);

	auto ret = pull_api_->StartPlay(pull_handle_);
	if ( NT_ERC_OK != ret )
	{
		if ( !is_pulling_ )
		{
			pull_api_->Close(pull_handle_);
			pull_handle_ = NULL;
		}

		return false;
	}

	is_playing_ = true;

	return true;
}

4. 拉流端关闭预览:

void nt_stream_relay_wrapper::StopPlay()
{
	if ( !is_playing_ )
		return;

	pull_api_->StopPlay(pull_handle_);

	if ( !is_pulling_ )
	{
		pull_api_->Close(pull_handle_);
		pull_handle_ = NULL;
	}

	is_playing_ = false;
}

5. 开始推流到RTMP服务器:

推流的流程,如之前所述,调用RTMP推送模块,然后数据源传编码后的音视频数据即可,下图的demo源码,同时展示了,RTSP流获取到后,转推RTMP的时候,数据解密的处理:

bool nt_stream_relay_wrapper::StartPush(const std::string& url)
{
	if ( is_pushing_ )
		return false;

	if ( url.empty() )
		return false;

	if ( !OpenPushHandle() )
		return false;

	auto push_handle = GetPushHandle();
	ASSERT(push_handle != nullptr);

	ASSERT(push_api_ != NULL);
	if ( NT_ERC_OK != push_api_->SetURL(push_handle, url.c_str(), NULL) )
	{
		if ( !is_started_rtsp_stream_ )
		{
			push_api_->Close(push_handle);
			SetPushHandle(nullptr);
		}

		return false;
	}

	// 加密测试 +++

	// push_api_->SetRtmpEncryptionOption(push_handle, url.c_str(), 1, 1);

	// NT_BYTE test_key[16] = {‘1‘, ‘2‘, ‘3‘};

	// push_api_->SetRtmpEncryptionKey(push_handle, url.c_str(), test_key, 16);

	// 加密测试 --

	if ( NT_ERC_OK != push_api_->StartPublisher(push_handle, NULL) )
	{
		if ( !is_started_rtsp_stream_ )
		{
			push_api_->Close(push_handle);
			SetPushHandle(nullptr);
		}

		return false;
	}

	// // test push rtsp ++

	// push_api_->SetPushRtspTransportProtocol(push_handle, 1);
	// // push_api_->SetPushRtspTransportProtocol(push_handle, 2);

	// push_api_->SetPushRtspURL(push_handle, "rtsp://player.daniulive.com:554/liverelay111.sdp");

	// push_api_->StartPushRtsp(push_handle, 0);

	// // test push rtsp--

	is_pushing_ = true;

	return true;
}

6. 传递转推RTMP数据:

void nt_stream_relay_wrapper::OnVideoDataHandle(NT_HANDLE handle, NT_UINT32 video_codec_id,
	NT_BYTE* data, NT_UINT32 size, NT_SP_PullStreamVideoDataInfo* info)
{
	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if ( pull_handle_ != handle )
		return;

	if (data == NULL)
		return;

	if (size < 1)
		return;

	if (info == NULL)
		return;

	std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);

	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if (push_handle_ == NULL)
		return;

	push_api_->PostVideoEncodedDataV2(push_handle_, video_codec_id,
		data, size, info->is_key_frame_, info->timestamp_, info->presentation_timestamp_);
}

void nt_stream_relay_wrapper::OnAudioDataHandle(NT_HANDLE handle, NT_UINT32 auido_codec_id,
	NT_BYTE* data, NT_UINT32 size, NT_SP_PullStreamAuidoDataInfo* info)
{
	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if (pull_handle_ != handle)
		return;

	if (data == NULL)
		return;

	if (size < 1)
		return;

	if (info == NULL)
		return;

	std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);

	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if (push_handle_ == NULL)
		return;

	push_api_->PostAudioEncodedData(push_handle_, auido_codec_id, data, size,
		info->is_key_frame_, info->timestamp_,
		info->parameter_info_, info->parameter_info_size_);
}

7. 关闭实时RTMP转推

void nt_stream_relay_wrapper::StopPush()
{
	if ( !is_pushing_ )
		return;

	is_pushing_ = false;

	std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);

	if ( nullptr == push_handle_ )
		return;

	push_api_->StopPublisher(push_handle_);

	// // test push rtsp ++
	// push_api_->StopPushRtsp(push_handle_);
	// // test push rtsp--

	if ( !is_started_rtsp_stream_ )
	{
		push_api_->Close(push_handle_);

		push_handle_ = nullptr;
	}
}

以上就是RTSP或RTMP流转RTMP推送的流程,感兴趣的开发者,可做设计参考。

原文地址:https://www.cnblogs.com/daniulivesdk/p/12250314.html

时间: 2024-08-26 14:21:52

如何实现多路海康大华等RTSP数据转RTMP推送的相关文章

海康/大华 IpCamera RTSP地址和格式

海康:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream说明:username: 用户名.例如admin.password: 密码.例如12345.ip: 为设备IP.例如 192.0.0.64.port: 端口号默认为554,若为默认可不填写.codec:有h264.MPEG-4.mpeg4这几种.channel: 通道号,起始为1.例如通道1,则为ch1.subtype: 码流类型,主码

海康&amp;大华&amp;DSS视频拉流-RTSP转RTMP多媒体播放技术

海康&大华&DSS获取RTSP 实时流 海康:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream说明:username: 用户名.例如admin.password: 密码.例如12345.ip: 为设备IP.例如 192.0.0.64.port: 端口号默认为554,若为默认可不填写.codec:有h264.MPEG-4.mpeg4这几种.channel: 通道号,起始为1.例如通道1

海康大华RTSP格式

海康实时流:rtsp://admin:[email protected]:554/h264/ch4/main/av_stream海康回放流(模拟通道):rtsp://admin:[email protected]:554/Streaming/tracks/101?starttime=20120802t063812z&endtime=20120802t064816z海康回放流(IP通道):    rtsp://admin:[email protected]:554/Streaming/tracks

浏览器低延时播放RTSP安防摄像头/海康大华硬盘录像机/NVR/流媒体服务器硬件开发机设备失去授权如何解决?

EasyNVR开发机是通过定制的硬件机器来运行对应的流媒体软件,因此硬件的授权是和开发机内部的软件相互绑定的,因此失去授权实际是软件授权出现了问题. 解决问题: 之前版本的授权方式是通过绑定机器的机器码来,设置对应的激活码来给对应的硬件设备上的软件进行授权,软件读取到对应的成功的激活码就进行成功授权. EasyNVR3.3.1版本正对软件版本授权有了优化,将之前的单纯的激活方式改为了Pem文件授权,更加方便了客户的授权,也提高了授权的安全性和稳定性.因此对应出现硬件授权不稳定的,可以联系相关技术

RTSP安防摄像头/海康大华硬盘录像机/NVR网页低延时播放流媒体服务器EasyNVR调取接口报Unauthorized如何解决?

随着雪亮工程.明厨亮灶.手机看店.智慧幼儿园监控等行业开始将传统的安防摄像头进行互联网.微信直播,我们知道摄像头直播的春天了.将安防摄像头或NVR上的视频流转成互联网直播常用的RTMP.HTTP-FLV.HLS等流格式再分发给用户端进行直播,不管身处何地都可以通过移动通讯设备查看监控设备,这些功能是EasyNVR互联网直播系统研发和设计的初衷和基础功能.另外EasyNVR增值功能是可通过接口二次集成在自己的原有的web业务系统实现网页.H5无插件实时直播. EasyNVR调取接口报Unautho

海康大华摄像头高起播低延时RTSP网页无插件流媒体播放器EasyPlayer-RTSP-Win录像和抓图实现线程优化方案分享

EasyPlayer-RTSP播放器是一套RTSP专用的播放器,包括有:Windows(支持IE插件,npapi插件).Android.iOS三个平台,是由青犀TSINGSEE开放平台开发和维护的区别于市面上大部分的通用播放器,EasyPlayer-RTSP系列从2014年初发展至今得到了各行各业(尤其是安防行业)的广泛应用,其主要原因是EasyPlayer-RTSP更加精炼.更加专注,具备低延时和高RTSP协议兼容性. ? EasyPlayer-RTSP-Win录像和抓图实现线程优化 测试发现

RTSP安防网络摄像头/海康大华硬盘录像机网页无插件直播流媒体服务器EasyNVR之鉴权接口的调用配置说明

进入移动互联网时代以来,企业微信公众号已成为除官网以外非常重要的宣传渠道,当3.2亿直播用户与9亿微信用户的势能累加,在微信上开启直播已成为越来越多企业的必然选择. EasyNVR核心在于摄像机的音视频流的获取.转换.转码与高性能分发,同时同步完成对实时直播流的录像存储,在客户端(PC浏览器.Android.iOS.微信)进行录像文件的检索.回放和下载. EasyNVR鉴权配置说明 发现问题 在实际对接项目中,很多用户需要根据自身业务层的用户权限,来决定调用视频流具体资源,EasyNVR在设计时

Onvif/RTSP海康大华网络安防摄像机网页无插件直播方案EasyNVR中直播页面和视频列表页面的区别介绍

背景分析 随着平安城市.智慧城市.雪亮工程.智能交通等各项建设的持续开展,安防逐渐得到普及,面对如此广阔的市场,对安防企业来说不仅仅是机遇更多的是挑战.现今大多数摄像头一直没能摆脱人工监控的传统监控方式,由此导致了大量视频数据堆积占用存储资源.实时性差.检索困难等问题,海量摄像头带来的海量视频数据检索工作需要耗费大量警力. 为了解决这些问题,近年来,视频监控行业发展方向主要为:“高清化.网络化.智能化”.视频监控设备技术性极强,系统的创新升级同时也在引导市场需求的变化并创造了新的市场需求.因此,

海康、大华IpCamera RTSP地址和格式

海康: rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream 说明: username: 用户名.例如admin. password: 密码.例如12345. ip: 为设备IP.例如 192.0.0.64. port: 端口号默认为554,若为默认可不填写. codec:有h264.MPEG-4.mpeg4这几种. channel: 通道号,起始为1.例如通道1,则为ch1. subtype