[Live-devel] live-devel Digest, Vol 30, Issue 33
Achraf Gazdar
achraf.gazdar at gmail.com
Fri Apr 28 01:19:29 PDT 2006
Mahdi,
>
> Dear Ross,
>
> RTCP "RR" packets are reaching the server but the
> program doesn't call the taskfunction and doesn't
> update videoSink->transmissionStatsDB().
> I can see the packet RTCP RR using ethereal.
>
> Thanks.
>
> /**********
> 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.,
> 59 Temple Place, Suite 330, Boston, MA 02111-1307
> USA
> **********/
> // Copyright (c) 1996-2005, Live Networks, Inc. All
> rights reserved
> // A test program that reads a MPEG-2 Transport Stream
> file,
> // and streams it using RTP
> // main program
>
> #include "liveMedia.hh"
> #include "BasicUsageEnvironment.hh"
> #include "GroupsockHelper.hh"
> #include "RTCP.hh"
>
> #define ADVANCE(n) pkt += (n); packetSize -= (n)
> // To stream using "source-specific multicast" (SSM),
> uncomment the following:
> //#define USE_SSM 1
> //#define IMPLEMENT_RTSP_SERVER 1
>
> #ifdef USE_SSM
> Boolean const isSSM = True;
> #else
> Boolean const isSSM = False;
> #endif
>
> // To set up an internal RTSP server, uncomment the
> following:
> //#define IMPLEMENT_RTSP_SERVER 1
> // (Note that this RTSP server works for multicast
> only)
>
> #define TRANSPORT_PACKET_SIZE 188
> #define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7
> // The product of these two numbers must be enough to
> fit within a network packet
>
> UsageEnvironment* env;
> char const* inputFileName = "tmp.mpg";
> FramedSource* videoSource;
> RTPSink* videoSink;
> RTCPInstance* rtcp;
> //RTPTransmissionStats* rtpstats;
>
> // char* destinationAddressStr = "127.0.0.1";
> char* destinationAddressStr = "239.255.42.42";
> unsigned short rtpPortNum = 1234;
> char* rtpPortNum_chai = "1234";
> unsigned short rtcpPortNum = 1235;
> char* rtcpPortNum_chai = "1235";
> unsigned char ttl = 7; // low, in case routers don't
> admin scope
>
> void play(); // forward
> void taskfunc_RR(void* /*clientData*/);
> void taskfunc_SR(void* /*clientData*/);
>
> int main() {
> // Begin by setting up our usage environment:
> TaskScheduler* scheduler =
> BasicTaskScheduler::createNew();
> env = BasicUsageEnvironment::createNew(*scheduler);
>
> // Create 'groupsocks' for RTP and RTCP:
> /* char* destinationAddressStr
> #ifdef USE_SSM
> = "127.0.0.1";
> #else
> = "127.0.0.1";
> /*#ifdef USE_SSM
> = "232.255.42.42";
> #else
> = "239.255.42.42";*/
> // Note: This is a multicast address. If you wish
> to stream using
> // unicast instead, then replace this string with
> the unicast address
> // of the (single) destination. (You may also need
> to make a similar
> // change to the receiver program.)
> //#endif
> /* const unsigned short rtpPortNum = 1234;
> const unsigned short rtcpPortNum = rtpPortNum+1;
> const unsigned char ttl = 7; // low, in case routers
> don't admin scope
> */
> struct in_addr destinationAddress;
> destinationAddress.s_addr =
> our_inet_addr(destinationAddressStr);
> const Port rtpPort(rtpPortNum);
> const Port rtcpPort(rtcpPortNum);
>
> Groupsock rtpGroupsock(*env, destinationAddress,
> rtpPort, ttl);
> Groupsock rtcpGroupsock(*env, destinationAddress,
> rtcpPort, ttl);
> #ifdef USE_SSM
> rtpGroupsock.multicastSendOnly();
> rtcpGroupsock.multicastSendOnly();
> #endif
>
> // Create an appropriate 'RTP sink' from the RTP
> 'groupsock':
> videoSink =
> SimpleRTPSink::createNew(*env, &rtpGroupsock, 33,
> 90000, "video", "mp2t",
> 1, True, False /*no 'M' bit*/);
>
> // Create (and start) a 'RTCP instance' for this RTP
> sink:
> const unsigned estimatedSessionBandwidth = 5000; //
> in kbps; for RTCP b/w share
> const unsigned maxCNAMElen = 100;
> unsigned char CNAME[maxCNAMElen+1];
> gethostname((char*)CNAME, maxCNAMElen);
> CNAME[maxCNAMElen] = '\0'; // just in case
> //#ifdef IMPLEMENT_RTSP_SERVER
> //#endif
> rtcp = RTCPInstance::createNew(*env, &rtcpGroupsock,
> estimatedSessionBandwidth, CNAME,
> videoSink, NULL /* we're a server */, isSSM);
> // Note: This starts RTCP running automatically
>
> //rtpstats=RTPTransmissionStats::createNew(videoSink,
>
> printf("mmm\n");
> rtcp->setRRHandler(taskfunc_RR,rtcp);
> rtcp->setSRHandler(taskfunc_SR,rtcp);
> printf("mmm\n");
> #ifdef IMPLEMENT_RTSP_SERVER
> RTSPServer* rtspServer =
> RTSPServer::createNew(*env);
> // Note that this (attempts to) start a server on
> the default RTSP server
> // port: 554. To use a different port number, add
> it as an extra
> // (optional) parameter to the
> "RTSPServer::createNew()" call above.
> if (rtspServer == NULL) {
> *env << "Failed to create RTSP server: " <<
> env->getResultMsg() << "\n";
> exit(1);
> }
> ServerMediaSession* sms
> = ServerMediaSession::createNew(*env,
> "testStream", inputFileName,
> "Session streamed by
> \"testMPEG2TransportStreamer\"",
> isSSM);
>
> sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink,
> rtcp));
> rtspServer->addServerMediaSession(sms);
>
> char* url = rtspServer->rtspURL(sms);
> *env << "Play this stream using the URL \"" << url
> << "\"\n";
> delete[] url;
> #endif
>
> // Finally, start the streaming:
> *env << "Beginning streaming...\n";
> play();
>
> env->taskScheduler().doEventLoop(); // does not
> return
>
> return 0; // only to prevent compiler warning
> }
>
> void taskfunc_RR(void* clientData)
> {
> /* unsigned char * pkt;
> unsigned packetSize=40;
> pkt=rtcp->get_fInBuf();
> for (unsigned i = 0; i < packetSize; ++i) {
> if (i%4 == 0) fprintf(stderr, " ");
> fprintf(stderr, "%02x", pkt[i]);
> }
> fprintf(stderr, "\n");
> ADVANCE(8);
> unsigned lossStats =
> ntohl(*(unsigned*)pkt); ADVANCE(4);
> unsigned highestReceived =
> ntohl(*(unsigned*)pkt); ADVANCE(4);
> unsigned jitter =
> ntohl(*(unsigned*)pkt); ADVANCE(4);
> unsigned timeLastSR =
> ntohl(*(unsigned*)pkt); ADVANCE(4);
> unsigned timeSinceLastSR =
> ntohl(*(unsigned*)pkt); ADVANCE(4);
> printf("%u\n",lossStats);
> printf("jitter 0x%08x\n",jitter);*/
> int
> packetLossRatio=-1,totNumPacketsLost=-1,jitterb=-1;
> RTPTransmissionStatsDB::Iterator
> statsIter(videoSink->transmissionStatsDB());
> // Assume that there's only one SSRC source
> (usually the case):
> RTPTransmissionStats* stats = statsIter.next();
> if (stats != NULL) {
> packetLossRatio = stats->packetLossRatio();
> totNumPacketsLost = stats->totNumPacketsLost();
> jitterb = stats->jitter();
> }
> // printf("\n\nkBytesTotal %d\n",packetLossRatio);
> // printf("totNumPacketsReceived
> %d\n",totNumPacketsLost);
> printf("jitter 0x%08x\n",jitterb);
> printf("RTCP RR recu\n");
> }
>
> void taskfunc_SR(void* clientData)
> {
> /* unsigned char * p;
> unsigned packetSize=40;
> p=rtcp->get_fInBuf();
> for (unsigned i = 0; i < packetSize; ++i) {
> if (i%4 == 0) fprintf(stderr, " ");
> fprintf(stderr, "%02x", p[i]);
> }
> fprintf(stderr, "\n");
> /* int nb;
> RTPTransmissionStatsDB& transmissionStatsDB =
> videoSink->transmissionStatsDB();
> nb=transmissionStatsDB.numReceivers();
> printf("%d\n",nb);*/
> // printf("%s\n",clientData);
> printf("RTCP SR recu\n");
> }
>
> void afterPlaying(void* /*clientData*/) {
> *env << "...done reading from file\n";
>
> Medium::close(videoSource);
> // Note that this also closes the input file that
> this source read from.
>
> play();
> }
>
> void play() {
> unsigned const inputDataChunkSize
> =
> TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;
>
> // Open the input file as a 'byte-stream file
> source':
> ByteStreamFileSource* fileSource
> = ByteStreamFileSource::createNew(*env,
> inputFileName, inputDataChunkSize);
> if (fileSource == NULL) {
> *env << "Unable to open file \"" << inputFileName
> << "\" as a byte-stream file source\n";
> exit(1);
> }
>
> // Create a 'framer' for the input source (to give
> us proper inter-packet gaps):
> videoSource =
> MPEG2TransportStreamFramer::createNew(*env,
> fileSource);
>
> // Finally, start playing:
> *env << "Beginning to read from file...\n";
> videoSink->startPlaying(*videoSource, afterPlaying,
> videoSink);
> }
>
>
>
>
>
>
>
>
>
>
>
>
>
> ___________________________________________________________________________
> Faites de Yahoo! votre page d'accueil sur le web pour retrouver
> directement vos services pr?f?r?s : v?rifiez vos nouveaux mails, lancez vos
> recherches et suivez l'actualit? en temps r?el.
> Rendez-vous sur http://fr.yahoo.com/set
>
>
> ------------------------------
>
> _______________________________________________
> live-devel mailing list
> live-devel at lists.live555.com
> http://lists.live555.com/mailman/listinfo/live-devel
>
>
> End of live-devel Digest, Vol 30, Issue 33
> ******************************************
>
Mahdi,
u can take a look to "playCommon.cpp" where Ross implements the QoS printing
feature based on (*sink->transmissionStatsDB).
By the Way I have used the same implementation to implement a QoS statistic
module in VLC (but not released, this is just implmented in our laboratory)
and it works fine.
Thnx
>
--
Achraf Gazdar
CRISTAL LAB
ENSI, Tunisia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.live555.com/pipermail/live-devel/attachments/20060428/b3c6eb48/attachment.html
More information about the live-devel
mailing list