EasyRTMP实现将RTSP流转换成RTMP推流实现RTSP直播转RTMP推流直播的功能

首先给大家推荐一下我老师大神的人工智能教学网站。教学不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵黄段子!点这里可以跳转到网站

EasyRTMP推流

EasyRTMP推流是一套调用简单、功能完善、运行高效稳定的RTMP功能组件,经过多年实战和线上运行打造,支持RTMP推送断线重连、环形缓冲、智能丢帧、网络事件回调,支持Windows、Linux、arm(hisiv100/hisiv200/hisiv300/hisiv400/hisiv500/hisiv600/etc…)、Android、iOS平台,支持市面上绝大部分的RTMP流媒体服务器,包括EasyDSS、Wowza、Red5、ngnix_rtmp、crtmpserver等主流RTMP服务器,能够完美应用于各种行业的直播需求,手机直播、桌面直播、摄像机直播、课堂直播等等方面!

EasyRTMP封装简化了整个RTMP协议流程,提供了一套非常简单易用的接口调用,Github上有多个基于EasyRTMP推流的Demo。Github地址:https://github.com/EasyDSS/EasyRTMP, Demo中EasyRTMP_RTSP项目是将RTSP流获取到本地进行RTMP推送,可进行RTMP推流直播。

RTSP视频源进行RTMP直播

目前安防项目上,基本都是RTSP流,无法接入RTMP服务器。EasyRTMP_RTSP Demo中通过libEasyRTSPClient库将RTSP数据流获取到本地,再讲获取来的音视频数据送给libEasyRTMP进行RTMP推送。如果获取来的数据不是AAC格式,而是G711、G726、PCM等格式,可以使用EasyDarwin团队提供的开源的EasyAACEncoder将音频数据转换成AAC格式再推送。这样可以实现将RTSP视频源实时的进行RTMP协议直播。

/* NVSource从RTSPClient获取数据后回调给上层 */
int Easy_APICALL __RTSPSourceCallBack( int _chid, void *_chPtr, int _mediatype, char *pbuf, RTSP_FRAME_INFO *frameinfo)
{
	if (NULL != frameinfo)
	{
		if (frameinfo->height==1088)		frameinfo->height=1080;
		else if (frameinfo->height==544)	frameinfo->height=540;
	}
	Easy_Bool bRet = 0;
	int iRet = 0;

	//目前只处理视频
	if (_mediatype == EASY_SDK_VIDEO_FRAME_FLAG)
	{
		if(frameinfo && frameinfo->length)
		{
			if( frameinfo->type == EASY_SDK_VIDEO_FRAME_I)
			{
				if(g_rtmpPusher.rtmpHandle == 0)
				{
					g_rtmpPusher.rtmpHandle = EasyRTMP_Create();

					bRet = EasyRTMP_Connect(g_rtmpPusher.rtmpHandle, SRTMP);
					if (!bRet)
					{
						printf("Fail to EasyRTMP_Connect ...\n");
					}

					EASY_MEDIA_INFO_T mediaInfo;
					memset(&mediaInfo, 0, sizeof(EASY_MEDIA_INFO_T));
					mediaInfo.u32VideoFps = 25;
					mediaInfo.u32AudioSamplerate = 8000;
					iRet = EasyRTMP_InitMetadata(g_rtmpPusher.rtmpHandle, &mediaInfo, 1024);
					if (iRet < 0)
					{
						printf("Fail to InitMetadata ...\n");
					}
				}

				EASY_AV_Frame avFrame;
				memset(&avFrame, 0, sizeof(EASY_AV_Frame));
				avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;
				avFrame.u32AVFrameLen = frameinfo->length;
				avFrame.pBuffer = (unsigned char*)pbuf;
				avFrame.u32VFrameType = EASY_SDK_VIDEO_FRAME_I;
				avFrame.u32TimestampSec = frameinfo->timestamp_sec;
				avFrame.u32TimestampUsec = frameinfo->timestamp_usec;
				
				iRet = EasyRTMP_SendPacket(g_rtmpPusher.rtmpHandle, &avFrame);
				if (iRet < 0)
				{
					printf("Fail to EasyRTMP_SendH264Packet(I-frame) ...\n");
				}
				else
				{
					printf("I");
				}
			}
			else
			{
				if(g_rtmpPusher.rtmpHandle)
				{
					EASY_AV_Frame avFrame;
					memset(&avFrame, 0, sizeof(EASY_AV_Frame));
					avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;
					avFrame.u32AVFrameLen = frameinfo->length-4;
					avFrame.pBuffer = (unsigned char*)pbuf+4;
					avFrame.u32VFrameType = EASY_SDK_VIDEO_FRAME_P;
					avFrame.u32TimestampSec = frameinfo->timestamp_sec;
					avFrame.u32TimestampUsec = frameinfo->timestamp_usec;
					iRet = EasyRTMP_SendPacket(g_rtmpPusher.rtmpHandle, &avFrame);
					if (iRet < 0)
					{
						printf("Fail to EasyRTMP_SendH264Packet(P-frame) ...\n");
					}
					else
					{
						printf("P");
					}
				}
			}				
		}	
	}
	else if (_mediatype == EASY_SDK_AUDIO_FRAME_FLAG)
	{
		EASY_AV_Frame	avFrame;
		memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
		avFrame.u32AVFrameFlag = EASY_SDK_AUDIO_FRAME_FLAG;
		avFrame.u32TimestampSec = frameinfo->timestamp_sec;
		avFrame.u32TimestampUsec = frameinfo->timestamp_usec;

		if(frameinfo->codec == EASY_SDK_AUDIO_CODEC_AAC)
		{
			avFrame.pBuffer = (Easy_U8*)(pbuf);
			avFrame.u32AVFrameLen  = frameinfo->length;	
			printf("*");
			iRet = EasyRTMP_SendPacket(g_rtmpPusher.rtmpHandle, &avFrame);
		}
		else if ((frameinfo->codec == EASY_SDK_AUDIO_CODEC_G711A) || (frameinfo->codec == EASY_SDK_AUDIO_CODEC_G711U) || (frameinfo->codec == EASY_SDK_AUDIO_CODEC_G726))
		{
			if(EasyInitAACEncoder(frameinfo) == 0)
			{
				memset(g_rtmpPusher.m_pAACEncBufer, 0, 64*1024);
				unsigned int iAACBufferLen = 0;

				if(Easy_AACEncoder_Encode(g_rtmpPusher.m_pAACEncoderHandle, (unsigned char*)pbuf,  frameinfo->length, g_rtmpPusher.m_pAACEncBufer, &iAACBufferLen) > 0)
				{
					printf("*");
					avFrame.pBuffer = (Easy_U8*)(g_rtmpPusher.m_pAACEncBufer);
					avFrame.u32AVFrameLen  = iAACBufferLen;	
					iRet = EasyRTMP_SendPacket(g_rtmpPusher.rtmpHandle, &avFrame);
				}
			}
		}
	}

	return 0;
}

EasyRTMP推流的成功应用

目前EasyRTMP推流在Easy系列的多款产品中使用,属于对内的技术中台组件、对外的开放平台组件,我们在将各种标准的、非标的、RTSP的、国标的、SDK的数据流接入进来后,都是通过EasyRTMP推流到EasyDSS流媒体服务器或者其他RTMP类型流媒体服务器,达到统一标准输出的目的。

EasyRTMP目前已经成功应用在了Easy系列的多款产品上,尤其是比较知名的EasyNVR智能云终端无插件服务产品、EasyDSS互联网流媒体服务器产品、EasyNVS视频集中管理平台产品、EasyGBS国标GB/T28181平台产品,这些产品都完完全全使用的是EasyPlayer.js:

更多流媒体音视频资源

EasyDarwin开源流媒体服务器:www.EasyDarwin.org

EasyDSS高性能互联网直播服务:www.EasyDSS.com

EasyNVR安防视频可视化服务:www.EasyNVR.com

EasyNVS视频综合管理平台:www.EasyNVS.com

EasyNTS云组网:www.EasyNTS.com

EasyGBS国标GB/T28181服务器:www.EasyGBS.com

EasyRTC视频会议解决方案:www.EasyRTC.cn

Copyright © TSINGSEE.com Team 2012-2019

青犀TSINGSEE

点这里可以跳转到人工智能网站

发表评论