Source code: Https://github.com/EasyDarwin orwww.easydarwin.org
In the two modes of real-time video forwarding in Darwin, we describe two modes of streaming media server for audio and video forwarding on the source side. One of the #拉模式 # forwards. It is often used in our usual projects. In the traditional video surveillance industry, for example, IP cameras are deployed to monitor every location in the intranet. We need to manage them centrally and publicly, and then we need to use a streaming server that pulls the audio and video streams of the required cameras and transforms them (such as rtmp, HTTP, etc.). As a relay to monitor intranet and public network, provide forwarding service.
#转发模块设计
Pull mode forwarding, the forwarding server as a rtspclient role, to the source side of the camera to obtain audio and video data. There is one aspect of the audio and video data that will be pulled into the role of the server. Once again as a data source, distributed to the client being requested. In this way, we need to consider the following points in the design:
- The data stream from the source side to the server can be reused, that is, a path-by-step.
- The server side maintains a list of all the camera sources that are being distributed.
- The server is not connected to the source side in the spare state, and the connection process is initiated only if it is required.
- When all client ends a request to a source end. The server stops fetching data from the source side. Disconnect.
The Darwin system already has some of the conditions we need: The Rtspclientclient implementation, the RTP distribution process (reflectorsession). We need to implement: The Darwin Pull mode forwarding module, we define this module name as Qtssondemandrelaymodule, which means that it is forwarded only when it is required; Darwin and the source are used to interact, save information, receive data clientsession , in order not to affect Darwin's original architecture, we did not change it directly in the Rtspclient class. Instead of defining the class yourself: Rtspclientsession, instantiate the Rtspclient object as its member variable:
In the rtspclientsession. All RTSP processes are completed by Fclient (Rtspclient object), Rtspclientsession is responsible for variable storage (such as server address Faddr, Portfport, Usernamefname, Passwordfpassword), receive packet statistics (fstates, fnumpacketreceived), Rtspclient control (Setup sends Fnumsetups, RTSP disconnects fteardownimmediately), and theIn
the case of non-client disconnection. The re-connection between server and camera。
#转发模块实现
Our named Pull mode forwarding module name is: Qtssondemandrelaymodule. It is necessary to implement the forwarding and processing of RTSP and RTP separately. In this way, we will handle Qtss_rtsppreprocessor_role (RTSP message processing), Qtss_rtsprelayingdata_role (RTP data processing), Qtss_, respectively. Clientsessionclosing_role (client or Rtspclientsession disconnect processing).
*qtss_rtsppreprocessor_role (RTSP message processing)
We designed the pull mode to forward the name and address map in the same way that the map list is configured in the XML file. When the qtssondemandrelaymodule is initialized, we load the configuration mapping table into the module, of course! We can also change the way we read a database:
Like what. The RTSP camera address is: RTSP://218.204.223.237:554/LIVE/1/66251FC11353191F/E7OOQWCFBQJOO80J.SDP,RTSP The forwarding server address is: 8.8.8.8. The port is: 554. Then client request: RTSP://8.8.8.8:554/IPC1, forwarding server will be to rtsp://218.204.223.237:554/live/1/66251fc11353191f/ E7OOQWCFBQJOO80J.SDP requests camera data, gets and forwards to the client list.
Mapping lookup We do in Dodescribe:
Qtss_error dodescribe (qtss_standardrtsp_params* inparams) {char* theuristr = NULL; Qtss_error err = qtss_getvalueasstring (inparams->inrtsprequest, qtssrtspreqfilename, 0, &THEURISTR); Assert (Err = = Qtss_noerr); if (err! = Qtss_noerr) return Qtssmoduleutils::senderrorresponse (inparams->inrtsprequest, qtssclientbadrequest, 0) ; Qtsschararraydeleter Theuristrdeleter (THEURISTR);//Find the configuration table, get the camera information structure deviceinfo* pdeviceinfo = parsedevice-> Getdeviceinfobyidname (THEURISTR); if (pdeviceinfo = = NULL) {//The mapping table does not find relevant information. Return, RTSP request to other modules to process return qtss_requestfailed;} Mapping information exists rtsp://218.204.223.237:554/live/1/66251fc11353191f/e7ooqwcfbqjoo80j.sdprtspclientsession* clientSes = null;//first Find out if the rtspclientsession hash table has established the corresponding camera Rtspclientsessionstrptrlen streamname (THEURISTR); osref* Clientsesref = Sclientsessionmap->resolve (&streamname); if (clientsesref! = NULL) {clientses = ( rtspclientsession*) Clientsesref->getobject ();} else{//first establish interaction between server and camera rtspclientsessionclientses = NEW RTSPClientsession (Socketutils::convertstringtoaddr (pdeviceinfo->m_szip), pdeviceinfo->m_nport,pdeviceinfo- >m_szsourceurl,1,rtcpinterval,0,thereadinterval,sockrcvbuf,speed,packetplayheader,overbufferwindowink, SENDOPTIONS,PDEVICEINFO->M_SZUSER,PDEVICEINFO->M_SZPASSWORD,THEURISTR);//Send describe request to the camera source Os_error Theerr = Clientses->senddescribe (); if (Theerr = = Qtss_noerr) {//will successfully build Rtspclientsession register into Sclientsessionmap table Os_ Error Theerr = Sclientsessionmap->register (Clientses->getref ()); Assert (Theerr = = Qtss_noerr);} Else{clientses->signal (task::kkillevent); return Qtssmoduleutils::senderrorresponse (inParams-> Inrtsprequest, Qtssclientnotfound, 0); }//adds an invalid reference to Rtspclientsession, which is then uniformly released osref* debug = Sclientsessionmap->resolve (&streamname); Assert (debug = = Clientses->getref ());} Establish the reflectorsession used for forwarding, perhaps the process is similar to qtssreflectormodule reflectorsession* thesession = setupproxysession (InParams, clientses); if (thesession = = NULL) {sclientsessionmap->release (CLIEntses->getref ()); Return Qtssmoduleutils::senderrorresponse (inparams->inrtsprequest, qtssservernotimplemented, 0);}}
Here we use two hash Map, one is storage rtspclientsession Sclientsessionmap, a storage reflectorsession ssessionmap.
*qtss_rtsprelayingdata_role (RTP data processing for fetching)
When Rtspclientsession gets to a RTP package. We'll call Qtss_rtsprelayingdata_role and send the RTP packet push to reflectorsession for distribution. The distribution process is the same as the Qtssreflectormodule processing method. The calling method also does the same:
*qtss_clientsessionclosing_role (client and Rtspclientsession disconnect processing)
Reflectorsessionclient reference count statistics, client-side disconnect process, rtspclientsession disconnect process. Basically the same as the Rtspsession (client and Device push) method:
void Removeoutput (reflectoroutput* inoutput, reflectorsession* insession, Bool16 killclients) {//Removed from reflectorsession Rtspsession Assert (insession); if (insession! = null) {if (inoutput! = null) insession->removeoutput (inoutput,true); Osmutexlocker Locker (Ssessi Onmap->getmutex ()); osref* thesessionref = Insession->getref (); if (thesessionref! = NULL) {if (thesessionref->getrefcount () = = 0) {//when When the number of client references is 0. Notifies rtspclientsession to disconnect from the camera rtspclientsession* proxysession = (rtspclientsession*) insession->getrelaysession () ; if (proxysession! = null) {proxysession->setreflectorsession (null); Sclientsessionmap->unregister ( Proxysession->getref ());p roxysession->signal (task::kkillevent);} Insession->setrelaysession (NULL); Ssessionmap->unregister (thesessionref);d elete insession; } else {qtss_printf ("QTSSReflector.cpp:RemoveOutput Release session=%lu REFCOunt=%d\n ", (UInt32) Insession,thesessionref->getrefcount ()); Ssessionmap->release (THESESSIONREF); }}} delete inoutput;}
#演示效果
#下载
Program Download:
http://pan.baidu.com/s/1c09vY6k, execute start.bat. Please see ReadMe.txt for detailed usage!
------------------------------------------------------------
This article turns from www.easydarwin.org, many other open source media solutions. Please pay attention to our: Easydarwin
Developing RTSP Cascade server with Darwin (pull mode forwarding) (source code)