live555推送实时视频流

这篇具有很好参考价值的文章主要介绍了live555推送实时视频流。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1,linux 环境:
官网上下载,下载地址:http://www.live555.com/liveMedia/public/
live555 版本:“2018.12.14”
参考:http://www.live555.com/liveMedia/faq.html 这个FAQ要仔细阅读。
2,编译
根据不同的平台来配置,并生成对应的Makefile
2.1 ARM平台:
修改交叉编译工具
cp config.armlinux config.arm
vi config.arm
CROSS_COMPILE?= arm-buildroot-linux-uclibcgnueabi-
生成Makefile: ./genMakefiles arm
2.2 Linux 64位平台(x86-64 ):
./genMakefiles linux-64bit
2.3 Linux 32位平台(x86):
./genMakefiles linux
make

生成mediaServer/live555MediaServer

3,测试
3.1,mediaServer下 会生成 live555MediaServer。
live555MediaServer test.264
如果出现Correct this by increasing “OutPacketBuffer::maxSize” to at least 186818, before creating this ‘RTPSink’. (Current value is 100000.)
在DynamicRTSPServer.cpp文件ServerMediaSession* createNewSMS()
里修改OutPacketBuffer::maxSize

if (strcmp(extension, ".264") == 0) {
    // Assumed to be a H.264 Video Elementary Stream file:
    NEW_SMS("H.264 Video");
    OutPacketBuffer::maxSize = 300000; //100000;// allow for some possibly large H.264 frames
    sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
  }


createNewSMS是在RTSP setup时调用的。
3.2,testProgs
testProgs 目录下各种测试文件,每个文件的作用和用法,官网上有详细的介绍。这些测试用例目前基本上都是以文件的形式作为输入源,下面重点介绍以实时流的形式作为输入源的2种方法。
主要是参考testH264VideoStreamer 和testOnDemandRTSPServer来修改。

4.不用读文件,使用实时视频流作为输入源

最简单的方法:将实时视频流推送到一个FIFO管道(或stdin),将文件名改为这个管道的文件名,这里不做详细介绍了。管道一次写数据4096。

4.1  方法1,rtsp_server_main.cpp

#include <liveMedia.hh>
#include <BasicUsageEnvironment.hh>
#include <GroupsockHelper.hh>
#include <rtsp_stream.h>

#include "LiveServerMediaSubsession.h"

#include <pthread.h>
#include "rtsp_server.h"


using namespace KHJ;

UsageEnvironment* env;

#ifdef RTSP_H265_SUPPORT
H265VideoStreamFramer* videoSource = NULL;
#else
H264VideoStreamFramer* videoSource = NULL;
#endif

RTPSink* videoSink;

pthread_t rtsp_server_thread_id;

void play(); // forward

void * rtsp_server_thread(void *) 
{
	// Begin by setting up our usage environment:
	TaskScheduler* scheduler = BasicTaskScheduler::createNew();
	env = BasicUsageEnvironment::createNew(*scheduler);

	OutPacketBuffer::maxSize = 512 * 1024;
	RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
	if (rtspServer == NULL) {
		*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
		exit(1);
	}
	
	
	ServerMediaSession* sms = ServerMediaSession::createNew(*env, "stream", "", 
												"Session streamed by \"testVideoStreamer\"", True);
												
	sms->addSubsession(KHJ::LiveServerMediaSubsession::createNew(*env));
	rtspServer->addServerMediaSession(sms);

	char* url = rtspServer->rtspURL(sms);
	*env << "Play this stream using the URL \"" << url << "\"\n";
	delete[] url;

	*env << "Beginning streaming...\n";
	//play();
	
	if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
		*env << "(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling, or for HTTP live streaming (for indexed Transport Stream files only).)\n";
	} else {
		*env << "(RTSP-over-HTTP tunneling is not available.)\n";
	}

	env->taskScheduler().doEventLoop(); 


}

void afterPlaying(void* /*clientData*/) {
	*env << "...done reading from file\n";
	videoSink->stopPlaying();
	if (videoSource)
	Medium::close(videoSource);
	play();
}

void play() 
{
	H265Source *fileSource = H265Source::createNew(*env);

	FramedSource* videoES = fileSource;

	#ifdef RTSP_H265_SUPPORT
	videoSource = H265VideoStreamFramer::createNew(*env, videoES);
	#else
	videoSource = H264VideoStreamFramer::createNew(*env, videoES);
	#endif

	// Finally, start playing:
	*env << "Beginning to read from file...\n";
	videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
}


int rtsp_server_start()
{
    int ret = 0;

    if((ret = pthread_create(&rtsp_server_thread_id, NULL, rtsp_server_thread, NULL)) <0 )
    {
        printf("create rtsp_server_thread fail\n");
    }

    return ret;
}

int rtsp_server_stop()
{
//    delete env;
//    delete videoSource;
    return 0;
}

#if 0
int main()
{
    rtsp_server_start();
    getchar();
}
#endif



4.2 方法2,参考testOnDemandRTSPServer
1)set the variable “reuseFirstSource” to “True”
2)根据类H264VideoFileServerMediaSubsession,新建一个新类H264LiveVideoServerMediaSubsession, implementation of the two pure virtual functions “createNewStreamSource()” and “createNewRTPSink()”
在createNewStreamSource()里用上面的H264LiveVideoSource代替ByteStreamFileSource。

H264VideoRTPSink继承关系:
H264VideoRTPSink->H264or5VideoRTPSink->VideoRTPSink->MultiFramedRTPSink->RTPSink->MediaSink->Medium。
H264VideoRTPSource继承关系:
H264VideoRTPSource->MultiFramedRTPSource->RTPSource->FramedSource->MediaSource->Medium.
H264VideoStreamFramer继承关系:
H264VideoStreamFramer->H264or5VideoStreamFramer->MPEGVideoStreamFramer->FramedFilter->FramedSource ->MediaSource->Medium.

下面列出具体实现


h265source.h

#ifndef MESAI_H265_SOURCE_HH
#define MESAI_H265_SOURCE_HH

#include <FramedSource.hh>
#include <UsageEnvironment.hh>
#include <Groupsock.hh>

namespace RTSP_DEMO
{
    
  class H265Source : public FramedSource {
  public:
    static H265Source* createNew(UsageEnvironment& env);
    ~H265Source();

  private:
    H265Source(UsageEnvironment& env);
    virtual void doGetNextFrame();
    virtual void doStopGettingFrames();
    
  private:
    int fp;

  };

}

#endif



h265source.cpp文件如下:

static int sfp[MAX_CLIENT_NUM] = {-1, -1, -1, -1};

namespace RTSP_DEMO
{
    H265Source * H265Source::createNew(UsageEnvironment& env) {
		return new H265Source(env);
	}

	H265Source::H265Source(UsageEnvironment& env) : FramedSource(env)
	{
        printf("%s--->%d\n", __FUNCTION__, __LINE__);

        int i=0;

        fp = -1;
        for(i=0; i<MAX_CLIENT_NUM; i++)
        {
            if(sfp[i] == -1)
            {
                fp = i;
                sfp[i] = fp;
                break;
            }
        }

        if(fp<0)
        {
            return;
        }

        memset(&client_frame_info[fp], 0, sizeof(client_frame_info[fp]));

        printf("%s--->%d, fp is %d\n", __FUNCTION__, __LINE__, fp);
	}

	H265Source::~H265Source()
	{
        printf("%s--->%d, fp is %d\n", __FUNCTION__, __LINE__, fp);

        int i=0;

        for(i=0; i<MAX_CLIENT_NUM; i++)
        {
            if(sfp[i] == fp)
            {
                fp = -1;
                sfp[i] = fp;
                break;
            }
        }

        printf("%s--->%d, fp is %d\n", __FUNCTION__, __LINE__, fp);
	}

	void H265Source::doStopGettingFrames()
	{
        printf("%s--->%d\n", __FUNCTION__, __LINE__);

        return ;
	}


	void H265Source::doGetNextFrame()
	{
		if (!isCurrentlyAwaitingData()) return;
		
		int ret = 0;
		int len = 10 * 1024;

//        printf("fMaxSize is %d\n", fMaxSize);
		
		if (len > fMaxSize)
			len = fMaxSize;
		
		gettimeofday(&fPresentationTime, NULL);
		
		
		fNumTruncatedBytes = 0;
	agin:

         if((ret = read_packet(fp, fTo, len)) > 0){
             fFrameSize = ret;
         }else{
            fFrameSize = 0;
         }
		
		if(fFrameSize>0)
			FramedSource::afterGetting(this);
		
	}
	
}


linve555常用修改点:

1, 输入的一帧数据最大值
StreamParser.cpp
#define BANK_SIZE 1500000 //帧越大,这个值就要越大

2, rtp buffer最大值
(1)Source端使用 MultiFramedRTPSource.cpp
BufferedPacket::BufferedPacket()
定义输入Buffer的上限值,即BufferedPacket的最大值
#define MAX_PACKET_SIZE 65536
(2)Sink端使用 MultiFramedRTPSink.cpp
#define RTP_PAYLOAD_MAX_SIZE 1456 //(1500-14-20-8)/4 *4 //ethernet=14,IP=20, UDP=8, a multiple of 4 bytes
MediaSink.cpp
静态变量OutPacketBuffer::maxSize = 600000; // allow for some possibly large H.265 frames,2000000 is by default
最好是RTP_PAYLOAD_MAX_SIZE的整数倍
值小了,会不断打印信息: Correct this by increasing “OutPacketBuffer::maxSize” to at least

,3,获取IP地址失败
RTSPServer::rtspURLPrefix(){
ourIPAddress(envir())
}

GroupsockHelper.cpp

 ourIPAddress()
 {
    if (badAddressForUs(from)) {
      #if 0
      char tmp[100];
      sprintf(tmp, "This computer has an invalid IP address: %s", AddressString(from).val());
      env.setResultMsg(tmp);
      from = 0;
      #endif
      struct ifreq req;
      int ret = 0;
      char szIpBuf[32];

      sock = socket(AF_INET, SOCK_DGRAM, 0);
      if (-1 != sock)
      {
          memset(&req, 0, sizeof(req));
          strncpy(req.ifr_name, "eth0", sizeof(req.ifr_name));
          ret = ioctl(sock, SIOCGIFADDR, &req);
          if (-1 == ret)
          {
            close(sock);
          }
          else
              {
               memset(&szIpBuf, 0, sizeof(szIpBuf));
             strcpy(szIpBuf, inet_ntoa(((struct sockaddr_in *)&req.ifr_addr)->sin_addr));
            close(sock);
            fromAddr.sin_addr.s_addr=our_inet_addr(szIpBuf);
            from = fromAddr.sin_addr.s_addr;
              }
      }
      else
        {
             char tmp[100];
         sprintf(tmp, "This computer has an invalid IP address: %s", AddressString(from).val());
         env.setResultMsg(tmp);
         from = 0;
        }
 }


3,内存泄漏点
RTCPInstance::processIncomingReport
if(NULL != reason)
{
delete[] reason;
reason = NULL;
}
在申请内存时加上上面释放语句
reason = new char[reasonLength + 1];
4,fill sei data DeltaTfiDivisor

H264or5VideoStreamParser::H264or5VideoStreamParser()
{
    //according to H264 and H265 spec, if not fill sei data, then         
frame_field_info_present_flag is zero. so need to set DeltaTfiDivisor to 2.0 in H264 and                         1.0 in H265
    if(fHNumber == 264) {
    DeltaTfiDivisor = 2.0;
    } else {
    DeltaTfiDivisor = 1.0;
    }
}


5,长时间拉取拉取RTSP流
报错误"Hit limit when reading incoming packet over TCP"
可考虑提高maxRTCPPacketSize的值
RTCP.CPP
static unsigned const maxRTCPPacketSize = 1456;

6,如播放越久延时越大
MultiFramedRTPSink.cpp->MultiFramedRTPSink::sendPacketIfNecessary() 最后延时列队uSecondsToGo 每帧都有延时时间。将uSecondsToGo 值赋为0。

7, 裁剪

只需留下这些目录(BasicUsageEnvironment、groupsock、liveMedia、mediaServer、UsageEnvironment),其它可删除掉。
其中liveMedia目录下有很多类型的文件,不需要的也可删除,同时修改
MediaSubsession::createSourceObjects()把相关类型的createNew也删除掉,否则编译失败。文章来源地址https://www.toymoban.com/news/detail-401971.html

到了这里,关于live555推送实时视频流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV获取网络摄像头实时视频流

    参考文章: [常用工具] OpenCV获取网络摄像头实时视频流_opencv网络摄像头 [常用工具] OpenCV获取网络摄像头实时视频流_opencv网络摄像头_落痕的寒假的博客-CSDN博客 在使用OpenCv处理视频时,无论是视频文件还是摄像头画面,都要使用VideoCapture类来进行每一帧图像的处理。当我们

    2024年02月01日
    浏览(57)
  • 设计一个像ESPN一样的实时视频流系统

    功能需求 •直播事件与流之间的最大延迟不超过1分钟•系统应能够适应大量用户(异构交付)•系统应能将视频转换为不同的分辨率和编解码器•系统应具备容错性 视频转换和接收 由于我们正在实时直播整个事件,因此我们不能等待整个视频结束后再开始将其转换为不同的

    2024年02月07日
    浏览(34)
  • 安防监控项目---mjpeg-streamer视频图像显示(实时视频流实现)

    书接上期,我们已经实现了许多功能了,但是对于视频流的实时上传还未实现,本期主要分享的就是如何具体实现网页实时显示摄像头采集到的视频,从而实现安防中监控的功能,这个功能完成后呢,就只剩下一个功能需求了,那就是GPRS模块,能够实现危险报警的功能,也能

    2024年02月06日
    浏览(47)
  • 【精选】基于OpenCV的实时视频流车牌识别(源码&教程)

    近年来,智能交通系统(ITS)在我国应用日益广泛。作为ITS重要组成部分的自动车牌识别系统在交通流量检测、交通诱导控制、违章车辆监控等方面有着广泛的应用,是确保道路安全畅通的重要手段,也为统计有关资料,为管理者决策提供有效数字依据的重要途径。由于一般的识别系

    2024年01月23日
    浏览(58)
  • FFmpeg+SDL实时解码和渲染H264视频流

    之前实现了Android手机摄像头数据的TCP实时传输,今天接着聊聊,如何在PC端把接收到的H264视频流实时解码并渲染出来。这次使用的语言是C++,框架有FFmpeg和SDL2。 解码部分使用FFmpeg,首先,需要初始化H264解码器: 然后,使用创建TCP连接到我们的Android端,读取数据包: 再把每

    2024年02月13日
    浏览(45)
  • Qt推流程序自动生成网页远程查看实时视频流(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)

    推流程序将视频流推送到流媒体服务器后,此时就等待验证拉流播放,一般可以选择ffplay命令行播放或者vlc等播放器打开播放,也可以选择网页直接打开拉流地址播放,一般主流的浏览器都支持网页直接播放hls/m3u8/webrtc类型的视频流,而且推流的主要目的可能就是为了能够在

    2024年02月05日
    浏览(75)
  • [chatGPT] 如何通过JNI在Android上显示实时视频流

    相机拍摄的画面通过local socket 获取,所以C++的代码可以轻易的获取到每一帧视频数据,需要通过JNI 让 Android显示出来,方法有两种,一种是在Android内创建回调函数使用Bitmap 和ImageView 进行赋值显示,另一种也就是ChatGPT完成的,Android将surface 传递到JNI层内,C++来完成赋值和渲

    2023年04月26日
    浏览(81)
  • 基于OpenCv+Django的网络实时视频流传输(前后端分离)

    秋风阁——北溪入江流:https://focus-wind.com/ 秋风阁——基于OpenCv+Django的网络实时视频流传输(前后端分离) 使用OpenCv捕获摄像机画面后,我们有时候需要将画面显示在界面上。本博客基于Django的前后端分离模式,将视频流从后端读取,传送给前端显示。 在使用Django进行视频

    2024年02月08日
    浏览(50)
  • VUE3 播放RTSP实时、回放(NVR录像机)视频流(使用WebRTC)

    1、下载webrtc-streamer,下载的最新window版本 Releases · mpromonet/webrtc-streamer · GitHub  2、解压下载包  3、webrtc-streamer.exe启动服务 (注意:这里可以通过当前文件夹下用cmd命令webrtc-streamer.exe -o这样占用cpu会很少,直接双击exe文件会占用cpu) cmd  webrtc-streamer.exe -o 启动如下图所示,

    2024年04月12日
    浏览(60)
  • Docker RTMP服务器搭建与视频流推送示例(流媒体服务器tiangolo/nginx-rtmp,推流客户端ffmpeg)

    在这篇文章中,我将详述如何搭建一个RTMP(Real-Time Messaging Protocol)服务器,并使用ffmpeg技术进行本地视频的推流。最后,我们将使用VLC播放器来播放这个RTMP流。 首先,我们需要搭建一个RTMP服务器。为了方便起见,我们将选择Docker作为服务器的环境。Docker的轻量化和可移植

    2024年01月17日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包