日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通过live555实现H264 RTSP直播

發(fā)布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通过live555实现H264 RTSP直播 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)載自:http://blog.csdn.net/firehood_/article/details/16844397

? ? ? 前面的文章中介紹了《H264視頻通過RTMP流直播》,下面將介紹一下如何將H264實時視頻通過RTSP直播。

? ? ? 實現(xiàn)思路是將視頻流發(fā)送給live555, 由live555來實現(xiàn)H264數(shù)據(jù)流直播。

? ? ? 視頻采集模塊通過FIFO隊列將H264數(shù)據(jù)幀發(fā)送給live555. live555 在收到客戶端的RTSP播放請求后,開始從FIFO中讀取H264視頻數(shù)據(jù)并通過RTSP直播出去。整個流程如下圖所示:


調(diào)整和修改Live555 MediaServer

? ? ? ? 下載live555源碼,在media目錄下增加四個文件并修改文件live555MediaServer.cpp。增加的四個文件如下:

WW_H264VideoServerMediaSubsession.h

WW_H264VideoServerMediaSubsession.cpp

?WW_H264VideoSource.h

WW_H264VideoSource.cpp

? ? ? ? 下面附上四個文件的源碼:

WW_H264VideoServerMediaSubsession.h

[cpp]?view plaincopy
  • #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?kbps??
  • ????virtual?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

    [cpp]?view plaincopy
  • #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);??//?ms??
  • ????????int?to_delay?=?delay?*?1000;??//?us??
  • ??
  • ????????nextTask()?=?envir().taskScheduler().scheduleDelayedTask(to_delay,?chkForAuxSDPLine,?this);??
  • ????}??
  • }??

  • WW_H264VideoSource.h

    [cpp]?view plaincopy
  • #ifndef?_WW_H264VideoSource_H??
  • #define?_WW_H264VideoSource_H??
  • ??
  • #include?"liveMedia.hh"??
  • #include?"BasicUsageEnvironment.hh"??
  • #include?"GroupsockHelper.hh"??
  • #include?"FramedSource.hh"??
  • ??
  • #define?FRAME_PER_SEC?25??
  • ??
  • class?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??

  • WW_H264VideoSource.cpp

    [cpp]?view plaincopy
  • #include?"WW_H264VideoSource.h"??
  • #include?<stdio.h>??
  • #ifdef?WIN32??
  • #include?<windows.h>??
  • #else??
  • #include?<sys/types.h>??
  • #include?<sys/stat.h>??
  • #include?<string.h>??
  • #include?<fcntl.h>??
  • #include?<unistd.h>??
  • #include?<limits.h>??
  • #endif??
  • ??
  • #define?FIFO_NAME?????"/tmp/H264_fifo"??
  • #define?BUFFER_SIZE???PIPE_BUF??
  • #define?REV_BUF_SIZE??(1024*1024)??
  • ??
  • #ifdef?WIN32??
  • #define?mSleep(ms)????Sleep(ms)??
  • #else??
  • #define?mSleep(ms)????usleep(ms*1000)??
  • #endif??
  • ??
  • ??
  • WW_H264VideoSource::WW_H264VideoSource(UsageEnvironment?&?env)?:???
  • FramedSource(env),??
  • m_pToken(0),??
  • m_pFrameBuffer(0),??
  • m_hFifo(0)??
  • {??
  • ????m_hFifo?=?open(FIFO_NAME,O_RDONLY);??
  • ????????printf("[MEDIA?SERVER]?open?fifo?result?=?[%d]\n",m_hFifo);??
  • ????if(m_hFifo?==?-1)??
  • ????{??
  • ????????return;??
  • ????}??
  • ??????
  • ????m_pFrameBuffer?=?new?char[REV_BUF_SIZE];??
  • ????if(m_pFrameBuffer?==?NULL)??
  • ????{??
  • ????????printf("[MEDIA?SERVER]?error?malloc?data?buffer?failed\n");??
  • ????????return;??
  • ????}??
  • ????memset(m_pFrameBuffer,0,REV_BUF_SIZE);??
  • }??
  • ??
  • WW_H264VideoSource::~WW_H264VideoSource(void)??
  • {??
  • ????if(m_hFifo)??
  • ????{??
  • ????????::close(m_hFifo);??
  • ????}??
  • ??????
  • ????envir().taskScheduler().unscheduleDelayedTask(m_pToken);??
  • ??
  • ????if(m_pFrameBuffer)??
  • ????{??
  • ????????delete[]?m_pFrameBuffer;??
  • ????????m_pFrameBuffer?=?NULL;??
  • ????}??
  • ??
  • ????printf("[MEDIA?SERVER]?rtsp?connection?closed\n");??
  • }??
  • ??
  • void?WW_H264VideoSource::doGetNextFrame()??
  • {??
  • ????//?根據(jù)?fps,計算等待時間??
  • ????double?delay?=?1000.0?/?(FRAME_PER_SEC?*?2);??//?ms??
  • ????int?to_delay?=?delay?*?1000;??//?us??
  • ??
  • ????m_pToken?=?envir().taskScheduler().scheduleDelayedTask(to_delay,?getNextFrame,?this);??
  • }??
  • ??
  • unsigned?int?WW_H264VideoSource::maxFrameSize()?const??
  • {??
  • ????return?1024*200;??
  • }??
  • ??
  • void?WW_H264VideoSource::getNextFrame(void?*?ptr)??
  • {??
  • ????((WW_H264VideoSource?*)ptr)->GetFrameData();??
  • }??
  • ??
  • void?WW_H264VideoSource::GetFrameData()??
  • {??
  • ????gettimeofday(&fPresentationTime,?0);??
  • ??
  • ????fFrameSize?=?0;??
  • ??
  • ????int?len?=?0;??
  • ????unsigned?char?buffer[BUFFER_SIZE]?=?{0};??
  • ????while((len?=?read(m_hFifo,buffer,BUFFER_SIZE))>0)??
  • ????{??
  • ????????memcpy(m_pFrameBuffer+fFrameSize,buffer,len);??
  • ????????fFrameSize+=len;??
  • ????}??
  • ????//printf("[MEDIA?SERVER]?GetFrameData?len?=?[%d],fMaxSize?=?[%d]\n",fFrameSize,fMaxSize);??
  • ??
  • ????//?fill?frame?data??
  • ????memcpy(fTo,m_pFrameBuffer,fFrameSize);??
  • ??
  • ????if?(fFrameSize?>?fMaxSize)??
  • ????{??
  • ????????fNumTruncatedBytes?=?fFrameSize?-?fMaxSize;??
  • ????????fFrameSize?=?fMaxSize;??
  • ????}??
  • ????else??
  • ????{??
  • ????????fNumTruncatedBytes?=?0;??
  • ????}??
  • ???????????????????
  • ????afterGetting(this);??
  • }??
  • [cpp]?view plaincopy
  • ??
  • 修改live555MediaServer.cpp文件如下

    [cpp]?view plaincopy
  • /**********?
  • This?library?is?free?software;?you?can?redistribute?it?and/or?modify?it?under?
  • the?terms?of?the?GNU?Lesser?General?Public?License?as?published?by?the?
  • Free?Software?Foundation;?either?version?2.1?of?the?License,?or?(at?your?
  • option)?any?later?version.?(See?<http://www.gnu.org/copyleft/lesser.html>.)?
  • ?
  • This?library?is?distributed?in?the?hope?that?it?will?be?useful,?but?WITHOUT?
  • ANY?WARRANTY;?without?even?the?implied?warranty?of?MERCHANTABILITY?or?FITNESS?
  • FOR?A?PARTICULAR?PURPOSE.??See?the?GNU?Lesser?General?Public?License?for?
  • more?details.?
  • ?
  • You?should?have?received?a?copy?of?the?GNU?Lesser?General?Public?License?
  • along?with?this?library;?if?not,?write?to?the?Free?Software?Foundation,?Inc.,?
  • 51?Franklin?Street,?Fifth?Floor,?Boston,?MA?02110-1301??USA?
  • **********/??
  • //?Copyright?(c)?1996-2013,?Live?Networks,?Inc.??All?rights?reserved??
  • //?LIVE555?Media?Server??
  • //?main?program??
  • ??
  • #include?<BasicUsageEnvironment.hh>??
  • #include?"DynamicRTSPServer.hh"??
  • #include?"version.hh"??
  • #include?"WW_H264VideoSource.h"??
  • #include?"WW_H264VideoServerMediaSubsession.h"??
  • ??
  • int?main(int?argc,?char**?argv)?{??
  • ????//?Begin?by?setting?up?our?usage?environment:??
  • ????TaskScheduler*?scheduler?=?BasicTaskScheduler::createNew();??
  • ????UsageEnvironment*?env?=?BasicUsageEnvironment::createNew(*scheduler);??
  • ??
  • ????UserAuthenticationDatabase*?authDB?=?NULL;??
  • #ifdef?ACCESS_CONTROL??
  • ????//?To?implement?client?access?control?to?the?RTSP?server,?do?the?following:??
  • ????authDB?=?new?UserAuthenticationDatabase;??
  • ????authDB->addUserRecord("username1",?"password1");?//?replace?these?with?real?strings??
  • ????//?Repeat?the?above?with?each?<username>,?<password>?that?you?wish?to?allow??
  • ????//?access?to?the?server.??
  • #endif??
  • ??
  • ????//?Create?the?RTSP?server:??
  • ????RTSPServer*?rtspServer?=?RTSPServer::createNew(*env,?554,?authDB);??
  • ????if?(rtspServer?==?NULL)?{??
  • ????????*env?<<?"Failed?to?create?RTSP?server:?"?<<?env->getResultMsg()?<<?"\n";??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????//?Add?live?stream??
  • ??
  • ????WW_H264VideoSource?*?videoSource?=?0;??
  • ??
  • ????ServerMediaSession?*?sms?=?ServerMediaSession::createNew(*env,?"live",?0,?"ww?live?test");??
  • ????sms->addSubsession(WW_H264VideoServerMediaSubsession::createNew(*env,?videoSource));??
  • ????rtspServer->addServerMediaSession(sms);??
  • ??
  • ????char?*?url?=?rtspServer->rtspURL(sms);??
  • ????*env?<<?"using?url?\""?<<?url?<<?"\"\n";??
  • ????delete[]?url;??
  • ??
  • ????//?Run?loop??
  • ????env->taskScheduler().doEventLoop();??
  • ??
  • ????rtspServer->removeServerMediaSession(sms);??
  • ??
  • ????Medium::close(rtspServer);??
  • ??
  • ????env->reclaim();??
  • ??
  • ????delete?scheduler;??
  • ??
  • ????return?1;??
  • }??

  • 發(fā)送H264視頻流的RTSPStream

    [cpp]?view plaincopy
  • /********************************************************************??
  • filename:???RTSPStream.h?
  • created:????2013-08-01?
  • author:?????firehood??
  • purpose:????通過live555實現(xiàn)H264?RTSP直播?
  • *********************************************************************/???
  • #pragma?once??
  • #include?<stdio.h>??
  • #ifdef?WIN32??
  • #include?<windows.h>??
  • #else??
  • #include?<pthread.h>??
  • #endif??
  • ??
  • #ifdef?WIN32??
  • typedef?HANDLE???????ThreadHandle;??
  • #define?mSleep(ms)???Sleep(ms)??
  • #else??
  • typedef?unsigned?int?SOCKET;??
  • typedef?pthread_t????ThreadHandle;??
  • #define?mSleep(ms)???usleep(ms*1000)??
  • #endif??
  • ??
  • #define?FILEBUFSIZE?(1024?*?1024)???
  • ??
  • ??
  • class?CRTSPStream??
  • {??
  • public:??
  • ????CRTSPStream(void);??
  • ????~CRTSPStream(void);??
  • public:??
  • ????//?初始化??
  • ????bool?Init();??
  • ????//?卸載??
  • ????void?Uninit();??
  • ????//?發(fā)送H264文件??
  • ????bool?SendH264File(const?char?*pFileName);??
  • ????//?發(fā)送H264數(shù)據(jù)幀??
  • ????int?SendH264Data(const?unsigned?char?*data,unsigned?int?size);??
  • };??

  • [cpp]?view plaincopy
  • /********************************************************************??
  • filename:???RTSPStream.cpp?
  • created:????2013-08-01?
  • author:?????firehood??
  • purpose:????通過live555實現(xiàn)H264?RTSP直播?
  • *********************************************************************/???
  • #include?"RTSPStream.h"??
  • #ifdef?WIN32??
  • #else??
  • #include?<sys/types.h>??
  • #include?<sys/stat.h>??
  • #include?<string.h>??
  • #include?<fcntl.h>??
  • #include?<unistd.h>??
  • #include?<limits.h>??
  • #include?<errno.h>??
  • #endif??
  • ??
  • #define?FIFO_NAME????"/tmp/H264_fifo"??
  • #define?BUFFERSIZE???PIPE_BUF??
  • ??
  • CRTSPStream::CRTSPStream(void)??
  • {??
  • ??????
  • }??
  • ??
  • CRTSPStream::~CRTSPStream(void)??
  • {??
  • ??????
  • }??
  • ??
  • bool?CRTSPStream::Init()??
  • {??
  • ????if(access(FIFO_NAME,F_OK)?==?-1)??
  • ????{??
  • ????????int?res?=?mkfifo(FIFO_NAME,0777);??
  • ????????if(res?!=?0)??
  • ????????{??
  • ????????????printf("[RTSPStream]?Create?fifo?failed.\n");??
  • ????????????return?false;??
  • ????????}??
  • ????}??
  • ????return?true;??
  • }??
  • ??
  • ??
  • void?CRTSPStream::Uninit()??
  • {??
  • ??????
  • }??
  • ??
  • bool?CRTSPStream::SendH264File(const?char?*pFileName)??
  • {??
  • ????if(pFileName?==?NULL)??
  • ????{??
  • ????????return?false;??
  • ????}??
  • ????FILE?*fp?=?fopen(pFileName,?"rb");????
  • ????if(!fp)????
  • ????{????
  • ????????printf("[RTSPStream]?error:open?file?%s?failed!",pFileName);??
  • ????}????
  • ????fseek(fp,?0,?SEEK_SET);??
  • ??
  • ????unsigned?char?*buffer??=?new?unsigned?char[FILEBUFSIZE];??
  • ????int?pos?=?0;??
  • ????while(1)??
  • ????{??
  • ????????int?readlen?=?fread(buffer+pos,?sizeof(unsigned?char),?FILEBUFSIZE-pos,?fp);??
  • ??
  • ????????if(readlen<=0)??
  • ????????{??
  • ????????????break;??
  • ????????}??
  • ??
  • ????????readlen+=pos;??
  • ??
  • ????????int?writelen?=?SendH264Data(buffer,readlen);??
  • ????????if(writelen<=0)??
  • ????????{??
  • ????????????break;??
  • ????????}??
  • ????????memcpy(buffer,buffer+writelen,readlen-writelen);??
  • ????????pos?=?readlen-writelen;??
  • ??
  • ????????mSleep(25);??
  • ????}??
  • ????fclose(fp);??
  • ????delete[]?buffer;??
  • ????return?true;??
  • }??
  • ??
  • //?發(fā)送H264數(shù)據(jù)幀??
  • int?CRTSPStream::SendH264Data(const?unsigned?char?*data,unsigned?int?size)??
  • {??
  • ????if(data?==?NULL)??
  • ????{??
  • ????????return?0;??
  • ????}??
  • ????//?open?pipe?with?non_block?mode??
  • ????int?pipe_fd?=?open(FIFO_NAME,?O_WRONLY|O_NONBLOCK);??
  • ????//printf("[RTSPStream]?open?fifo?result?=?[%d]\n",pipe_fd);??
  • ????if(pipe_fd?==?-1)??
  • ????{??
  • ????????return?0;??
  • ????}??
  • ???
  • ????int?send_size?=?0;??
  • ????int?remain_size?=?size;??
  • ????while(send_size?<?size)??
  • ????{??
  • ????????int?data_len?=?(remain_size<BUFFERSIZE)???remain_size?:?BUFFERSIZE;??
  • ????????int?len?=?write(pipe_fd,data+send_size,data_len);??
  • ????????if(len?==?-1)??
  • ????????{??
  • ????????????static?int?resend_conut?=?0;??
  • ????????????if(errno?==?EAGAIN?&&?++resend_conut<=3)??
  • ????????????{??
  • ????????????????printf("[RTSPStream]?write?fifo?error,resend..\n");??
  • ????????????????continue;??
  • ????????????}??
  • ????????????resend_conut?=?0;??
  • ????????????printf("[RTSPStream]?write?fifo?error,errorcode[%d],send_size[%d]\n",errno,send_size);??
  • ????????????break;??
  • ????????}??
  • ????????else??
  • ????????{????
  • ????????????send_size+=?len;??
  • ????????????remain_size-=?len;??
  • ????????}??
  • ????}??
  • ????close(pipe_fd);??
  • ????//printf("[RTSPStream]?SendH264Data?datalen[%d],?sendsize?=?[%d]\n",size,send_size);??
  • ????return?0;??
  • }??

  • 測試程序代碼

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?"RTSPStream.h"??
  • ??
  • int?main(int?argc,char*?argv[])??
  • {??
  • ????CRTSPStream?rtspSender;??
  • ????bool?bRet?=?rtspSender.Init();??
  • ????rtspSender.SendH264File("E:\\測試視頻\\test.264");??
  • ????system("pause");????
  • }??




  • FROM: ?http://www.cppblog.com/tx7do/archive/2014/05/31/207155.html

    總結(jié)

    以上是生活随笔為你收集整理的通过live555实现H264 RTSP直播的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。