Mahdi,<br>
<br><br><div><span class="gmail_quote"></span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br><br>Dear Ross,<br><br>RTCP &quot;RR&quot; packets are reaching the server but the
<br>program doesn't call the taskfunction and doesn't<br>update videoSink-&gt;transmissionStatsDB().<br>I can see the packet RTCP RR using ethereal.<br><br>Thanks.<br><br>/**********<br>This library is free software; you can redistribute it
<br>and/or modify it under<br>the terms of the GNU Lesser General Public License as<br>published by the<br>Free Software Foundation; either version 2.1 of the<br>License, or (at your<br>option) any later version. (See<br>
&lt;<a href="http://www.gnu.org/copyleft/lesser.html">http://www.gnu.org/copyleft/lesser.html</a>&gt;.)<br><br>This library is distributed in the hope that it will<br>be useful, but WITHOUT<br>ANY WARRANTY; without even the implied warranty of
<br>MERCHANTABILITY or FITNESS<br>FOR A PARTICULAR PURPOSE.&nbsp;&nbsp;See the GNU Lesser General<br>Public License for<br>more details.<br><br>You should have received a copy of the GNU Lesser<br>General Public License<br>along with this library; if not, write to the Free
<br>Software Foundation, Inc.,<br>59 Temple Place, Suite 330, Boston, MA&nbsp;&nbsp;02111-1307<br>USA<br>**********/<br>// Copyright (c) 1996-2005, Live Networks, Inc.&nbsp;&nbsp;All<br>rights reserved<br>// A test program that reads a MPEG-2 Transport Stream
<br>file,<br>// and streams it using RTP<br>// main program<br><br>#include &quot;liveMedia.hh&quot;<br>#include &quot;BasicUsageEnvironment.hh&quot;<br>#include &quot;GroupsockHelper.hh&quot;<br>#include &quot;RTCP.hh&quot;
<br><br>#define ADVANCE(n) pkt += (n); packetSize -= (n)<br>// To stream using &quot;source-specific multicast&quot; (SSM),<br>uncomment the following:<br>//#define USE_SSM 1<br>//#define IMPLEMENT_RTSP_SERVER 1<br><br>#ifdef USE_SSM
<br>Boolean const isSSM = True;<br>#else<br>Boolean const isSSM = False;<br>#endif<br><br>// To set up an internal RTSP server, uncomment the<br>following:<br>//#define IMPLEMENT_RTSP_SERVER 1<br>// (Note that this RTSP server works for multicast
<br>only)<br><br>#define TRANSPORT_PACKET_SIZE 188<br>#define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7<br>// The product of these two numbers must be enough to<br>fit within a network packet<br><br>UsageEnvironment* env;<br>
char const* inputFileName = &quot;tmp.mpg&quot;;<br>FramedSource* videoSource;<br>RTPSink* videoSink;<br>RTCPInstance* rtcp;<br>//RTPTransmissionStats* rtpstats;<br><br>//&nbsp;&nbsp;char* destinationAddressStr = &quot;<a href="http://127.0.0.1">
127.0.0.1</a>&quot;;<br>&nbsp;&nbsp;char* destinationAddressStr = &quot;<a href="http://239.255.42.42">239.255.42.42</a>&quot;;<br>&nbsp;&nbsp;unsigned short rtpPortNum = 1234;<br>&nbsp;&nbsp;char* rtpPortNum_chai = &quot;1234&quot;;<br>&nbsp;&nbsp;unsigned short rtcpPortNum = 1235;
<br>&nbsp;&nbsp;char* rtcpPortNum_chai = &quot;1235&quot;;<br>&nbsp;&nbsp;unsigned char ttl = 7; // low, in case routers don't<br>admin scope<br><br>void play(); // forward<br>void taskfunc_RR(void* /*clientData*/);<br>void taskfunc_SR(void* /*clientData*/);
<br><br>int main() {<br>&nbsp;&nbsp;// Begin by setting up our usage environment:<br>&nbsp;&nbsp;TaskScheduler* scheduler =<br>BasicTaskScheduler::createNew();<br>&nbsp;&nbsp;env = BasicUsageEnvironment::createNew(*scheduler);<br><br>&nbsp;&nbsp;// Create 'groupsocks' for RTP and RTCP:
<br>/*&nbsp;&nbsp;char* destinationAddressStr<br>#ifdef USE_SSM<br>&nbsp;&nbsp;&nbsp;&nbsp;= &quot;<a href="http://127.0.0.1">127.0.0.1</a>&quot;;<br>#else<br>&nbsp;&nbsp;&nbsp;&nbsp;= &quot;<a href="http://127.0.0.1">127.0.0.1</a>&quot;;<br>/*#ifdef USE_SSM<br>&nbsp;&nbsp;&nbsp;&nbsp;= &quot;
<a href="http://232.255.42.42">232.255.42.42</a>&quot;;<br>#else<br>&nbsp;&nbsp;&nbsp;&nbsp;= &quot;<a href="http://239.255.42.42">239.255.42.42</a>&quot;;*/<br>&nbsp;&nbsp;// Note: This is a multicast address.&nbsp;&nbsp;If you wish<br>to stream using<br>&nbsp;&nbsp;// unicast instead, then replace this string with
<br>the unicast address<br>&nbsp;&nbsp;// of the (single) destination.&nbsp;&nbsp;(You may also need<br>to make a similar<br>&nbsp;&nbsp;// change to the receiver program.)<br>//#endif<br>/*&nbsp;&nbsp;const unsigned short rtpPortNum = 1234;<br>&nbsp;&nbsp;const unsigned short rtcpPortNum = rtpPortNum+1;
<br>&nbsp;&nbsp;const unsigned char ttl = 7; // low, in case routers<br>don't admin scope<br>*/<br>&nbsp;&nbsp;struct in_addr destinationAddress;<br>&nbsp;&nbsp;destinationAddress.s_addr =<br>our_inet_addr(destinationAddressStr);<br>&nbsp;&nbsp;const Port rtpPort(rtpPortNum);
<br>&nbsp;&nbsp;const Port rtcpPort(rtcpPortNum);<br><br>&nbsp;&nbsp;Groupsock rtpGroupsock(*env, destinationAddress,<br>rtpPort, ttl);<br>&nbsp;&nbsp;Groupsock rtcpGroupsock(*env, destinationAddress,<br>rtcpPort, ttl);<br>#ifdef USE_SSM<br>&nbsp;&nbsp;rtpGroupsock.multicastSendOnly
();<br>&nbsp;&nbsp;rtcpGroupsock.multicastSendOnly();<br>#endif<br><br>&nbsp;&nbsp;// Create an appropriate 'RTP sink' from the RTP<br>'groupsock':<br>&nbsp;&nbsp;videoSink =<br>&nbsp;&nbsp;&nbsp;&nbsp;SimpleRTPSink::createNew(*env, &amp;rtpGroupsock, 33,<br>90000, &quot;video&quot;, &quot;mp2t&quot;,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
1, True, False /*no 'M' bit*/);<br><br>&nbsp;&nbsp;// Create (and start) a 'RTCP instance' for this RTP<br>sink:<br>&nbsp;&nbsp;const unsigned estimatedSessionBandwidth = 5000; //<br>in kbps; for RTCP b/w share<br>&nbsp;&nbsp;const unsigned maxCNAMElen = 100;
<br>&nbsp;&nbsp;unsigned char CNAME[maxCNAMElen+1];<br>&nbsp;&nbsp;gethostname((char*)CNAME, maxCNAMElen);<br>&nbsp;&nbsp;CNAME[maxCNAMElen] = '\0'; // just in case<br>//#ifdef IMPLEMENT_RTSP_SERVER<br>//#endif<br>&nbsp;&nbsp;rtcp = RTCPInstance::createNew(*env, &amp;rtcpGroupsock,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;estimatedSessionBandwidth,
CNAME,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;videoSink,
NULL /* we're a server */, isSSM);<br>&nbsp;&nbsp;// Note: This starts RTCP running automatically<br><br>//rtpstats=RTPTransmissionStats::createNew(videoSink,<br><br>printf(&quot;mmm\n&quot;);<br>rtcp-&gt;setRRHandler(taskfunc_RR,rtcp);
<br>rtcp-&gt;setSRHandler(taskfunc_SR,rtcp);<br>printf(&quot;mmm\n&quot;);<br>#ifdef IMPLEMENT_RTSP_SERVER<br>&nbsp;&nbsp;RTSPServer* rtspServer =<br>RTSPServer::createNew(*env);<br>&nbsp;&nbsp;// Note that this (attempts to) start a server on
<br>the default RTSP server<br>&nbsp;&nbsp;// port: 554.&nbsp;&nbsp;To use a different port number, add<br>it as an extra<br>&nbsp;&nbsp;// (optional) parameter to the<br>&quot;RTSPServer::createNew()&quot; call above.<br>&nbsp;&nbsp;if (rtspServer == NULL) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;*env &lt;&lt; &quot;Failed to create RTSP server: &quot; &lt;&lt;<br>env-&gt;getResultMsg() &lt;&lt; &quot;\n&quot;;<br>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;ServerMediaSession* sms<br>&nbsp;&nbsp;&nbsp;&nbsp;= ServerMediaSession::createNew(*env,<br>
&quot;testStream&quot;, inputFileName,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&quot;Session streamed by<br>\&quot;testMPEG2TransportStreamer\&quot;&quot;,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
isSSM);<br><br>sms-&gt;addSubsession(PassiveServerMediaSubsession::createNew(*videoSink,<br>rtcp));<br>&nbsp;&nbsp;rtspServer-&gt;addServerMediaSession(sms);<br><br>&nbsp;&nbsp;char* url = rtspServer-&gt;rtspURL(sms);<br>&nbsp;&nbsp;*env &lt;&lt; &quot;Play this stream using the URL \&quot;&quot; &lt;&lt; url
<br>&lt;&lt; &quot;\&quot;\n&quot;;<br>&nbsp;&nbsp;delete[] url;<br>#endif<br><br>&nbsp;&nbsp;// Finally, start the streaming:<br>&nbsp;&nbsp;*env &lt;&lt; &quot;Beginning streaming...\n&quot;;<br>&nbsp;&nbsp;play();<br><br>&nbsp;&nbsp;env-&gt;taskScheduler().doEventLoop(); // does not
<br>return<br><br>&nbsp;&nbsp;return 0; // only to prevent compiler warning<br>}<br><br>void taskfunc_RR(void* clientData)<br>{<br>/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned char * pkt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned packetSize=40;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pkt=rtcp-&gt;get_fInBuf();
<br>&nbsp;&nbsp;&nbsp;&nbsp;for (unsigned i = 0; i &lt; packetSize; ++i) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (i%4 == 0) fprintf(stderr, &quot; &quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;%02x&quot;, pkt[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;\n&quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADVANCE(8);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned
lossStats =<br>ntohl(*(unsigned*)pkt); ADVANCE(4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned highestReceived =<br>ntohl(*(unsigned*)pkt); ADVANCE(4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned jitter =<br>ntohl(*(unsigned*)pkt); ADVANCE(4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned timeLastSR =
<br>ntohl(*(unsigned*)pkt); ADVANCE(4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned timeSinceLastSR =<br>ntohl(*(unsigned*)pkt); ADVANCE(4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%u\n&quot;,lossStats);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;jitter 0x%08x\n&quot;,jitter);*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int<br>packetLossRatio=-1,totNumPacketsLost=-1,jitterb=-1;<br>&nbsp;&nbsp;&nbsp;&nbsp;RTPTransmissionStatsDB::Iterator<br>statsIter(videoSink-&gt;transmissionStatsDB());<br>&nbsp;&nbsp;&nbsp;&nbsp;// Assume that there's only one SSRC source<br>(usually the case):
<br>&nbsp;&nbsp;&nbsp;&nbsp;RTPTransmissionStats* stats = statsIter.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;if (stats != NULL) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;packetLossRatio = stats-&gt;packetLossRatio();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;totNumPacketsLost = stats-&gt;totNumPacketsLost();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jitterb = stats-&gt;jitter();
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;\n\nkBytesTotal %d\n&quot;,packetLossRatio);<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;totNumPacketsReceived<br>%d\n&quot;,totNumPacketsLost);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;jitter 0x%08x\n&quot;,jitterb);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;RTCP RR recu\n&quot;);<br>}<br><br>void taskfunc_SR(void* clientData)<br>{<br>/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned char * p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned packetSize=40;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p=rtcp-&gt;get_fInBuf();<br>&nbsp;&nbsp;&nbsp;&nbsp;for (unsigned i = 0; i &lt; packetSize; ++i) {
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (i%4 == 0) fprintf(stderr, &quot; &quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;%02x&quot;, p[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;\n&quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nb;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RTPTransmissionStatsDB&amp; transmissionStatsDB =
<br>videoSink-&gt;transmissionStatsDB();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nb=transmissionStatsDB.numReceivers();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%d\n&quot;,nb);*/<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s\n&quot;,clientData);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;RTCP SR recu\n&quot;);
<br>}<br><br>void afterPlaying(void* /*clientData*/) {<br>&nbsp;&nbsp;*env &lt;&lt; &quot;...done reading from file\n&quot;;<br><br>&nbsp;&nbsp;Medium::close(videoSource);<br>&nbsp;&nbsp;// Note that this also closes the input file that<br>this source read from.
<br><br>&nbsp;&nbsp;play();<br>}<br><br>void play() {<br>&nbsp;&nbsp;unsigned const inputDataChunkSize<br>&nbsp;&nbsp;&nbsp;&nbsp;=<br>TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;<br><br>&nbsp;&nbsp;// Open the input file as a 'byte-stream file<br>source':
<br>&nbsp;&nbsp;ByteStreamFileSource* fileSource<br>&nbsp;&nbsp;&nbsp;&nbsp;= ByteStreamFileSource::createNew(*env,<br>inputFileName, inputDataChunkSize);<br>&nbsp;&nbsp;if (fileSource == NULL) {<br>&nbsp;&nbsp;&nbsp;&nbsp;*env &lt;&lt; &quot;Unable to open file \&quot;&quot; &lt;&lt; inputFileName
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;&lt; &quot;\&quot; as a byte-stream file source\n&quot;;<br>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br>&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;// Create a 'framer' for the input source (to give<br>us proper inter-packet gaps):<br>&nbsp;&nbsp;videoSource =<br>MPEG2TransportStreamFramer::createNew(*env,
<br>fileSource);<br><br>&nbsp;&nbsp;// Finally, start playing:<br>&nbsp;&nbsp;*env &lt;&lt; &quot;Beginning to read from file...\n&quot;;<br>&nbsp;&nbsp;videoSink-&gt;startPlaying(*videoSource, afterPlaying,<br>videoSink);<br>}<br><br><br><br><br><br>
<br><br><br><br><br><br><br>___________________________________________________________________________<br>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.<br>Rendez-vous sur <a href="http://fr.yahoo.com/set">http://fr.yahoo.com/set</a><br><br><br>------------------------------<br><br>_______________________________________________
<br>live-devel mailing list<br><a href="mailto:live-devel@lists.live555.com">live-devel@lists.live555.com</a><br><a href="http://lists.live555.com/mailman/listinfo/live-devel">http://lists.live555.com/mailman/listinfo/live-devel
</a><br><br><br>End of live-devel Digest, Vol 30, Issue 33<br>******************************************<br></blockquote></div>Mahdi,<br>
u can take a look to &quot;playCommon.cpp&quot; where Ross implements the QoS printing feature based on (*sink-&gt;transmissionStatsDB).<br>
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.<br>
<br>
Thnx <br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"></blockquote>
<br><br clear="all"><br>-- <br>Achraf Gazdar<br>CRISTAL LAB<br>ENSI, Tunisia