通过live555实现H264 RTSP直播

前面的文章中介绍了《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"class WW_H264VideoServerMediaSubsession : public OnDemandServerMediaSubsession{public:WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source);~WW_H264VideoServerMediaSubsession(void);public:virtual char const * getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource);virtual FramedSource * createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate); // "estBitrate" is the stream’s estimated bitrate, in kbpsvirtual RTPSink * createNewRTPSink(Groupsock * rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource * inputSource);static WW_H264VideoServerMediaSubsession * createNew(UsageEnvironment & env, FramedSource * source);static void afterPlayingDummy(void * ptr);static void chkForAuxSDPLine(void * ptr);void chkForAuxSDPLine1();private:FramedSource * m_pSource;char * m_pSDPLine;RTPSink * m_pDummyRTPSink;char m_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){return new WW_H264VideoServerMediaSubsession(env, source);}FramedSource * WW_H264VideoServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate){return H264VideoStreamFramer::createNew(envir(), new WW_H264VideoSource(envir()));}RTPSink * WW_H264VideoServerMediaSubsession::createNewRTPSink(Groupsock * rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource * inputSource){return H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);}char const * WW_H264VideoServerMediaSubsession::getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource){if (m_pSDPLine){return m_pSDPLine;}m_pDummyRTPSink = rtpSink;//mp_dummy_rtpsink->startPlaying(*source, afterPlayingDummy, this);m_pDummyRTPSink->startPlaying(*inputSource, 0, 0);chkForAuxSDPLine(this);m_done = 0;envir().taskScheduler().doEventLoop(&m_done);m_pSDPLine = strdup(m_pDummyRTPSink->auxSDPLine());m_pDummyRTPSink->stopPlaying();return m_pSDPLine;}void WW_H264VideoServerMediaSubsession::afterPlayingDummy(void * ptr){WW_H264VideoServerMediaSubsession * This = (WW_H264VideoServerMediaSubsession *)ptr;This->m_done = 0xff;}void WW_H264VideoServerMediaSubsession::chkForAuxSDPLine(void * ptr){WW_H264VideoServerMediaSubsession * This = (WW_H264VideoServerMediaSubsession *)ptr;This->chkForAuxSDPLine1();}void WW_H264VideoServerMediaSubsession::chkForAuxSDPLine1(){if (m_pDummyRTPSink->auxSDPLine()){m_done = 0xff;}else{double delay = 1000.0 / (FRAME_PER_SEC); // msint to_delay = delay * 1000; // usnextTask() = envir().taskScheduler().scheduleDelayedTask(to_delay, chkForAuxSDPLine, this);}}WW_H264VideoSource.h#ifndef _WW_H264VideoSource_H#define _WW_H264VideoSource_H#include "liveMedia.hh"#include "BasicUsageEnvironment.hh"#include "GroupsockHelper.hh"#include "FramedSource.hh"#define FRAME_PER_SEC 25class WW_H264VideoSource : public FramedSource{public:WW_H264VideoSource(UsageEnvironment & env);~WW_H264VideoSource(void);public:virtual void doGetNextFrame();virtual unsigned int maxFrameSize() const;static void getNextFrame(void * ptr);void GetFrameData();private:void *m_pToken;char *m_pFrameBuffer;int m_hFifo;};#endif漫过心际的孤独,早已蔚然成冰,而你是这个季节里最美的音符。

通过live555实现H264 RTSP直播

相关文章:

你感兴趣的文章:

标签云: