[Live-devel] RTCP
Msakni Mehdi
mehdi18832001 at yahoo.fr
Thu Apr 27 23:08:30 PDT 2006
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
More information about the live-devel
mailing list