Analysis on the realization of LIVE555 Media Library real-time stream preview

Source: Internet
Author: User
Tags fread


As described earlier, the media files can be played through live555. This article mainly talk about real-time streaming through live555 playback.

Relative to the previous file stream, here live streams only need to implement a subclass: by inheriting the Rtspserver class to implement some of their own related operations.

Such as: There is a client request, you need to find the corresponding session through Lookupservermediasession, here can define their own streamname, that is, the URL after a string,. If not found, create a new build of the different sessions you need, as well as populate your own SDP information and so on.

The subclass of inheriting Rtspserver is implemented as follows: Specific implementations can refer to the implementation of Rtspserver, only need to modify the session to fill their own.

#include "DemoH264RTSPServer.h" #include "DemoH264Interface.h" #include "DemoH264MediaSubsession.h" demoh264rtspserver* demoh264rtspserver::createnew (usageenvironment& env, Port Rtspport, userauthenticationdatabase* authdatabase, unsigned reclamationtestseconds) {int rtspsock = -1;rtspsock = SetUpOurSocket (env, Rtspport); if (Rtspsock = =-1) {Dbg_live555_print ("Setupoursocket failed\n"); return NULL;} return new Demoh264rtspserver (env, Rtspsock, Rtspport, Authdatabase, reclamationtestseconds);} Demoh264rtspserver::D emoh264rtspserver (usageenvironment& env, int oursock, Port rtspport, userauthenticationdatabase* authdatabase,unsigned reclamationtestseconds): Rtspserver (env, OurSock, RtspPort, Authdatabase, Reclamationtestseconds), Frtspserverstate (True) {Dbg_live555_print ("Create Demoh264rtspserver \ n");} Demoh264rtspserver::~demoh264rtspserver () {}servermediasession* demoh264rtspserver::lookupservermediasession ( Const char* Streamname) {//Streamname, as a string following the URL address such as//Rtsp://10.0.2.15/streaMnamech00streamtype00, then Streamname = "streamnamech00streamtype00";//when the client sends a URL request, it can parse streamname to determine which stream of the channel is requested//1  Parse URL I do not handle here, can own callback interface come in processing int channelno = 0;  Channel number int streamtype = 0;  bitstream type int videotype = 1;  Video or audio int requesttype = 0; Request type Live Preview or playback servermediasession* SMS = Null;switch (requesttype) {case 0://Realtime SMS = Rtspserver::lookupserverme Diasession (Streamname); if (NULL = = SMS) {SMS = Servermediasession::createnew (EnviR (), streamname, NULL, NULL);D Emoh264mediasubsession *session = demoh264mediasubsession::createnew (EnviR (), Streamtype, VideoType, ChannelNO, False ); Sms->addsubsession (session);} Break;case 1://play Backdbg_live555_print ("Play back Request!\n") Break;default:dbg_live555_print ("Unknown request Type!\n "); break;} This->addservermediasession (SMS); return SMS;} Demoh264rtspserver::D emoh264rtspclientsession* demoh264rtspserver::createnewclientsession (unsigned Clientsessionid, int clientsocket, struct sockaddr_in clientaddr) {Demoh264rtspserVer::D emoh264rtspclientsession* client = new Demoh264rtspclientsession (*this, Clientsessionid, Clientsocket, CLIENTADDR); fclientsessionlist.push_back (client);D bg_live555_print ("Add client session success!\n"); return client;} int Demoh264rtspserver::stopdemoh264rtspserver () {//delete all clients Sessionstd::list<demoh264rtspserver::D Emoh264rtspclientsession*>:: Iterator pos =this->fclientsessionlist.begin (); for (pos; pos! = this-> Fclientsessionlist.end (); POS + +) {demoh264rtspserver::D emoh264rtspclientsession* tmp = *pos;delete tmp;} Delete this; return 0;} Demoh264rtspserver::D emoh264rtspclientsession::D emoh264rtspclientsession (demoh264rtspserver& rtspServer, unsigned clietnsessionid, int clientsocket, struct sockaddr_in clientaddr): Rtspserver::rtspclientsession (RTSPServer, Clietnsessionid, Clientsocket, clientaddr) {}demoh264rtspserver::D emoh264rtspclientsession::~ Demoh264rtspclientsession () {/*std::list<demoh264rtspserver::D emoh264rtspclientsession*>:: Iterator pos = (( DemoH264rtspserver&) fourserver). Fclientsessionlist.begin (); for (pos; pos! = ((demoh264rtspserver&) fourserver). Fclientsessionlist.end (); POS + +) {if ((*pos)->foursessionid = = This->foursessionid) {((demoh264rtspserver&) fourserver). Fclientsessionlist.erase (POS);D Bg_live555_print ("Client session has been delete!\n"); */}
#include "DemoH264FrameSource.h" #include "DemoH264Interface.h" Demoh264framesource::D Emoh264framesource ( usageenvironment& env, long sourcehandle, int sourcetype): Framedsource (env), Fsourcehandle (SourceHandle), Flastbufsize (0), fleftdatasize (0), Fsourcetype (sourcetype), Ffirstframe (1) {//Open streaming media file, in live stream, Here is some preparatory work before starting the flow of the stream fdatabuf = (char*) malloc (2*1024*1024), if (fdatabuf = = NULL) {dbg_live555_print ("Create source data BUF failed!\n ");}} Demoh264framesource::~demoh264framesource () {if (fdatabuf) {free (FDATABUF); fdatabuf = NULL;}} demoh264framesource* demoh264framesource::createnew (usageenvironment& env, int streamtype, int channelNO, int sourcetype) {//through Streamtype and Channelno to create source, request the corresponding code stream to the front//Long SourceHandle = Openstreamhandle (Channelno, Streamtype); if (SourceHandle = = 0) {dbg_live555_print ("open the source stream failed!\n"); return NULL;} Dbg_live555_print ("Create H264framesource!\n"); return new Demoh264framesource (env, SourceHandle, sourcetype);} /* Get the total length of the file that needs to be read, live555 a length limit on each data transmission */long filesize (FILE *stream) {long curpos, Length;curpos = Ftell (stream); Fseek (Stream, 0L, seek_end); length = Ftell (stre AM); fseek (Stream, CurPos, seek_set); return length;} void Demoh264framesource::d ogetnextframe () {int ret = 0;//invokes the device interface to get a frame of data if (fleftdatasize = = 0) {ret = Getstreamdata ( Fsourcehandle, Fdatabuf,&flastbufsize, &fleftdatasize,fsourcetype); if (ret <= 0) {dbg_live555_print (" Getstreamdata failed!\n "); return;}} int fnewframesize = fleftdatasize;if (Fnewframesize > Fmaxsize) {//the fmaxsize data Fframesize = fmaxsize;fnumtruncate Dbytes = Fnewframesize-fmaxsize;fleftdatasize = fnewframesize-fmaxsize;//Note the use of the Memmove function, allowing the memory space overlay Memmove (FTo, Fdatabuf, fframesize); Memmove (Fdatabuf, Fdatabuf+fmaxsize, fleftdatasize);}         else {//all the data fframesize = fnewframesize;fleftdatasize = 0; Memmove (FTo, Fdatabuf, fframesize);} Gettimeofday (&fpresentationtime, NULL), if (ffirstframe) {fdurationinmicroseconds = 40000;nexttask () = EnviR (). TaskScheduler (). ScheduledelayeDtask (100000, (taskfunc*) framedsource::aftergetting, this); ffirstframe = 0;} Else{framedsource::aftergetting (this);}} void Demoh264framesource::d ostopgetframe () {closestreamhandle (fsourcehandle);}
session subclasses implement
#include "DemoH264MediaSubsession.h" #include "DemoH264FrameSource.h" #include "DemoH264Interface.h" #include " H264videostreamframer.hh "#include" h264videortpsink.hh "Demoh264mediasubsession::D emoh264mediasubsession ( usageenvironment& env, int streamtype, int videotype, int channelno, bool Reusefirstsource, Portnumbits InitalNumPort ): Ondemandservermediasubsession (env, Reusefirstsource), Fstreamtype (Streamtype), Fvideotype (VideoType), FChannelNO (Channelno) {}demoh264mediasubsession::~demoh264mediasubsession () {}demoh264mediasubsession* DemoH264MediaSubsession:: CreateNew (usageenvironment& env, int streamtype, int videotype, int channelno, bool reusefirstsource, portnumbits INI Talnumport) {demoh264mediasubsession* SMS = new Demoh264mediasubsession (env, Streamtype, Videotype, ChannelNO, Reusefirstsource, initalnumport); return SMS;} framedsource* Demoh264mediasubsession::createnewstreamsource (unsigned clientsessionid, unsigned& estBitrate) { Dbg_live555_print ("Create new Stream source!\n"));//This creates different source objects depending on the type of actual request if (Fvideotype = = 0x01) {//H264 video estbitrate = $;//kbps Demoh264framesource * source = Demoh264framesource::createnew (EnviR (), Fstreamtype, Fchannelno, 0), if (Source = = NULL) {dbg_live555_print ("Create Source failed videotype:%d!\n ", Fvideotype); return NULL;} Return H264videostreamframer::createnew (EnviR (), source);} else if (Fvideotype = = 0x2) {//Mpeg-4 video}else if (Fvideotype = = 0x04) {//G711 audio estbitrate = +;//Kbps Demo H264framesource * Source = demoh264framesource::createnew (EnviR (), Fstreamtype, Fchannelno, 1); if (Source = = NULL) {dbg_l Ive555_print ("Create Source failed videotype:%d!\n", Fvideotype); return NULL;} return source;} else {//Unknow Type}return NULL;} rtpsink* Demoh264mediasubsession::createnewrtpsink (groupsock* rtpgroupsock, unsigned char rtppayloadtypeifdynamic, framedsource* inputsource) {//Here you can create different sink depending on the type///depending on the actual development needs, inherit different subclasses Dbg_live555_print ("Createnewrtpnk videotype:%d !\n ", fvideotype); if (Fvideotype = = 0x01{return h264videortpsink::createnew (EnviR (), Rtpgroupsock, rtppayloadtypeifdynamic);} else if (Fvideotype = = 0x02) {//Mpeg-4}else if (Fvideotype = = 0x04) {//G711 Audio}else {//Unknow type; return NULL;}} /* Fill in the SDP information according to the actual development *//*char const* Demoh264mediasubsession::sdplines () {//Create SDP info return fsdplines;} */
the last interface class, mainly encapsulates some live555 processing operations and real-time access to stream data interface (you can write a callback or other according to the actual situation, see how to achieve convenience), convenient for other places to call.

#include "DemoH264Interface.h" #include "DemoH264RTSPServer.h"/* open real-time bitstream handle */long openstreamhandle (int channelno, int Streamtype) {//Start some preparations for real-time streaming: Get a handle to this type of real-time stream, facilitate direct get stream at the back//I test here, so still read with your own defined file stream, but each time is read a frame of data//file stream format for frameheader_s + H264 + frameheader_s + H264 ... file* fp = fopen ("stream264file.h264", "rb+"), if (NULL = = fp) {dbg_live555_print ("open Streamhandle failed!\n"); return-1 ;} Return (long) FP; /* Get a frame of data in real time */int getstreamdata (Long lhandle, char* buf, unsigned* bufsize, unsigned* leftbufsize, int sourcetype) {if ( Lhandle <= 0) {dbg_live555_print ("Lhandle error!\n"); return-1;} framehead_s Stframehead;memset (&stframehead, 0, sizeof (framehead_s)); file* fp = (file*) lhandle;int Readlen = 0;//1, first read the header information of a frame of data Readlen = Fread (&stframehead, 1, sizeof (framehead_s), FP); (Readlen! = sizeof (framehead_s)) {Dbg_live555_print ("read Frame Header Failed!\n"); return-1;} 2, get a frame H264 real-time data if (Stframehead.framelen > 2*1024*1024)//In source Databuf means assigned 2m{dbg_live555_print ("Data is too Long:framlen=%d\n ", stframehead.framelen);//Reallocate memory processing return 0;} Readlen = Fread (buf, 1, Stframehead.framelen, FP); if (Readlen! = Stframehead.framelen) {dbg_live555_print ("read Frame RawData failed!\n "); return-1;} return Stframehead.framelen;} /* Turn off the stream handle */void closestreamhandle (long Lhandle) {///Some cleanup work for the off Stream fclose ((file*) lhandle);} demoh264interface* demoh264interface::m_instance = null;demoh264interface* demoh264interface::createnew () {if (NULL = = m_instance) {m_instance = new demoh264interface ();} return m_instance;} Demoh264interface::D emoh264interface () {M_liveserverflag = false;} Demoh264interface::~demoh264interface () {}void demoh264interface::initlive555 (void *param) {//Initialize Dbg_live555_print ("~~~~init live555 stream\n");//Begin by setting up the live555 usage environment M_scheduler = Basictaskscheduler::crea Tenew (); m_env = Basicusageenvironment::createnew (*m_scheduler); #if Access_control//Authentication m_authdb = new Userauthenticationdatabase;m_authdb->adduserrecord ("username", "password"); #endif m_rtspserver = NUll;m_rtspserverportnum = 554; You can modify M_liveserverflag = true;} int demoh264interface::startlive555 () {if (!m_liveserverflag) {dbg_live555_print ("not Init the live server!\n"); return -1; }dbg_live555_print ("~~~~start live555 stream\n");//Set up RTSP service m_rtspserver = demoh264rtspserver::createnew (*m_env, m_ Rtspserverportnum, M_AUTHDB); if (m_rtspserver = = NULL) {//*m_env << "Create Rtspserver Failed:" << m_env-> Getresultmsg () << "\ n";D bg_live555_print ("Create Rtspserver failed:%s\n", m_env->getresultmsg ()); return-1;} Loop and not come Back~m_env->taskscheduler (). Doeventloop (); return 0;} int demoh264interface::stoplive555 () {dbg_live555_print ("~~~~stop live555 stream\n"), if (M_liveserverflag) {if (m_ Rtspserver) M_rtspserver->stopdemoh264rtspserver (); m_liveserverflag = false;}}
Finally, it is equivalent to a demo calling program:

#include <stdio.h> #include "DemoH264Interface.h" int main (int argc, char* argv[]) {//init//add some RTSP service information that needs to be set, such as user name, password port, etc., pass the parameter void* param = null;demoh264interface::createnew ()->initlive555 (param);//Start if (-1 = = Demoh264interface::createnew ()->startlive555 ()) {Dbg_live555_print ("Start live555 moudle failed!\n"); return 0;} Stop Demoh264interface::createnew ()->stoplive555 (); return 0;}

After I have done these things, my test under Windows is a normal preview of the J results as follows:


But in the Linux system seems to be no, there is a problem, the error is as follows:


Did not find the stream, troubleshooting a few days also did not check out the reason, in the Internet to see other users of the doubts, seemingly said TrackID wrong, but I have only one ID here, should not cause this problem, the estimated etiology is not here,

Because there is no research on the source of the implementation, so temporarily failed to locate the problem, I hope to have encountered the hero know the reason to tell me, I will be very grateful.


The full path to the above code can be downloaded here: live555 full code


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Analysis on the realization of LIVE555 Media Library real-time stream preview

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.