前面的文章中介绍了《H264视频通过RTMP流直播》,下面将介绍一下如何将H264实时视频通过RTSP直播。
实现思路是将视频流发送给live555, 由live555来实现H264数据流直播。
视频采集模块通过FIFO队列将H264数据帧发送给live555. live555 在收到客户端的RTSP播放请求后,开始从FIFO中读取H264视频数据并通过RTSP直播出去。整个流程如下图所示:
调整和修改Live555 MediaServer
下载live555源码,在media目录下增加四个文件并修改文件live555MediaServer.cpp。增加的四个文件如下:
WW_H264VideoServerMediaSubsession.h
WW_H264VideoServerMediaSubsession.cpp
WW_H264VideoSource.h
WW_H264VideoSource.cpp
下面附上四个文件的源码:
WW_H264VideoServerMediaSubsession.h
#pragma once
#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
#include "GroupsockHelper.hh"
#include "OnDemandServerMediaSubsession.hh"
#include "WW_H264VideoSource.h"
classWW_H264VideoServerMediaSubsession :publicOnDemandServerMediaSubsession
{
public:
WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source);
~WW_H264VideoServerMediaSubsession(void);
public:
virtualcharconst* getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource);
virtualFramedSource * createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate);// "estBitrate" is the stream's estimated bitrate, in kbps
virtualRTPSink * createNewRTPSink(Groupsock * rtpGroupsock, unsignedcharrtpPayloadTypeIfDynamic, FramedSource * inputSource);
staticWW_H264VideoServerMediaSubsession * createNew(UsageEnvironment & env, FramedSource * source);
staticvoidafterPlayingDummy(void* ptr);
staticvoidchkForAuxSDPLine(void* ptr);
voidchkForAuxSDPLine1();
private:
FramedSource * m_pSource;
char* m_pSDPLine;
RTPSink * m_pDummyRTPSink;
charm_done;
};
WW_H264VideoServerMediaSubsession.cpp
#include "WW_H264VideoServerMediaSubsession.h"
WW_H264VideoServerMediaSubsession::WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source) : OnDemandServerMediaSubsession(env, True)
{
m_pSource = source;
m_pSDPLine = 0;
}
WW_H264VideoServerMediaSubsession::~WW_H264VideoServerMediaSubsession(void)
{
if(m_pSDPLine)
{
free(m_pSDPLine);
}
}
WW_H264VideoServerMediaSubsession * WW_H264VideoServerMediaSubsession::createNew(UsageEnvironment & env, FramedSource * source)
{
returnnewWW_H264VideoServerMediaSubsession(env, source);
}
FramedSource * WW_H264VideoServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate)
{
returnH264VideoStreamFramer::createNew(envir(),newWW_H264VideoSource(envir()));
}
RTPSink * WW_H264VideoServerMediaSubsession::createNewRTPSink(Groupsock * rtpGroupsock, unsigned charrtpPayloadTypeIfDynamic, FramedSource * inputSource)
{
returnH264VideoRTPSin