[SCM] liblivemedia packaging branch, master, updated. debian/2010.02.10-1-8-gd744cce

xtophe-guest at users.alioth.debian.org xtophe-guest at users.alioth.debian.org
Tue Apr 20 23:24:18 UTC 2010


The following commit has been merged in the master branch:
commit 347fd79f33c3c5b4a94548950142f165af733682
Author: Christophe Mutricy <xtophe at videolan.org>
Date:   Tue Apr 20 22:31:01 2010 +0100

    Imported Upstream version 2010.04.09

diff --git a/BasicUsageEnvironment/BasicUsageEnvironment.cpp b/BasicUsageEnvironment/BasicUsageEnvironment.cpp
index 73c2d31..a201012 100644
--- a/BasicUsageEnvironment/BasicUsageEnvironment.cpp
+++ b/BasicUsageEnvironment/BasicUsageEnvironment.cpp
@@ -54,26 +54,27 @@ int BasicUsageEnvironment::getErrno() const {
 }
 
 UsageEnvironment& BasicUsageEnvironment::operator<<(char const* str) {
-	fprintf(stderr, "%s", str);
-	return *this;
+  if (str == NULL) str = "(NULL)"; // sanity check
+  fprintf(stderr, "%s", str);
+  return *this;
 }
 
 UsageEnvironment& BasicUsageEnvironment::operator<<(int i) {
-	fprintf(stderr, "%d", i);
-	return *this;
+  fprintf(stderr, "%d", i);
+  return *this;
 }
 
 UsageEnvironment& BasicUsageEnvironment::operator<<(unsigned u) {
-	fprintf(stderr, "%u", u);
-	return *this;
+  fprintf(stderr, "%u", u);
+  return *this;
 }
 
 UsageEnvironment& BasicUsageEnvironment::operator<<(double d) {
-	fprintf(stderr, "%f", d);
-	return *this;
+  fprintf(stderr, "%f", d);
+  return *this;
 }
 
 UsageEnvironment& BasicUsageEnvironment::operator<<(void* p) {
-	fprintf(stderr, "%p", p);
-	return *this;
+  fprintf(stderr, "%p", p);
+  return *this;
 }
diff --git a/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh b/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
index a6fe223..f64c7e2 100644
--- a/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
+++ b/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
@@ -4,7 +4,7 @@
 #ifndef _BASICUSAGEENVIRONMENT_VERSION_HH
 #define _BASICUSAGEENVIRONMENT_VERSION_HH
 
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING	"2010.02.10"
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT		1265760000
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING	"2010.04.09"
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT		1270771200
 
 #endif
diff --git a/UsageEnvironment/include/UsageEnvironment_version.hh b/UsageEnvironment/include/UsageEnvironment_version.hh
index bc46ed9..e936928 100644
--- a/UsageEnvironment/include/UsageEnvironment_version.hh
+++ b/UsageEnvironment/include/UsageEnvironment_version.hh
@@ -4,7 +4,7 @@
 #ifndef _USAGEENVIRONMENT_VERSION_HH
 #define _USAGEENVIRONMENT_VERSION_HH
 
-#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING	"2010.02.10"
-#define USAGEENVIRONMENT_LIBRARY_VERSION_INT		1265760000
+#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING	"2010.04.09"
+#define USAGEENVIRONMENT_LIBRARY_VERSION_INT		1270771200
 
 #endif
diff --git a/config.armlinux b/config.armlinux
index 3e604f7..f827c48 100644
--- a/config.armlinux
+++ b/config.armlinux
@@ -1,16 +1,16 @@
-CROSS_COMPILE=		arm-elf-
+CROSS_COMPILE?=		arm-elf-
 COMPILE_OPTS =		$(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
 C =			c
 C_COMPILER =		$(CROSS_COMPILE)gcc
 C_FLAGS =		$(COMPILE_OPTS)
 CPP =			cpp
-CPLUSPLUS_COMPILER =	$(CROSS_COMPILE)gcc
+CPLUSPLUS_COMPILER =	$(CROSS_COMPILE)g++
 CPLUSPLUS_FLAGS =	$(COMPILE_OPTS) -Wall -DBSD=1
 OBJ =			o
-LINK =			$(CROSS_COMPILE)gcc -o
-LINK_OPTS =		-L.
+LINK =			$(CROSS_COMPILE)g++ -o
+LINK_OPTS =		
 CONSOLE_LINK_OPTS =	$(LINK_OPTS)
-LIBRARY_LINK =		$(CROSS_COMPILE)ar cr
+LIBRARY_LINK =		$(CROSS_COMPILE)ar cr 
 LIBRARY_LINK_OPTS =	$(LINK_OPTS)
 LIB_SUFFIX =			a
 LIBS_FOR_CONSOLE_APPLICATION =
diff --git a/config.armlinux b/config.armlinux.orig
similarity index 100%
copy from config.armlinux
copy to config.armlinux.orig
diff --git a/config.armlinux.rej b/config.armlinux.rej
new file mode 100644
index 0000000..49e7c9b
--- /dev/null
+++ b/config.armlinux.rej
@@ -0,0 +1,35 @@
+***************
+*** 1,16 ****
+- CROSS_COMPILE=		arm-elf-
+  COMPILE_OPTS =		$(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
+  C =			c
+  C_COMPILER =		$(CROSS_COMPILE)gcc
+  C_FLAGS =		$(COMPILE_OPTS)
+  CPP =			cpp
+- CPLUSPLUS_COMPILER =	$(CROSS_COMPILE)gcc
+  CPLUSPLUS_FLAGS =	$(COMPILE_OPTS) -Wall -DBSD=1
+  OBJ =			o
+- LINK =			$(CROSS_COMPILE)gcc -o
+- LINK_OPTS =		-L.
+  CONSOLE_LINK_OPTS =	$(LINK_OPTS)
+- LIBRARY_LINK =		$(CROSS_COMPILE)ar cr
+  LIBRARY_LINK_OPTS =	$(LINK_OPTS)
+  LIB_SUFFIX =			a
+  LIBS_FOR_CONSOLE_APPLICATION =
+--- 1,16 ----
++ CROSS_COMPILE?=		arm-elf-
+  COMPILE_OPTS =		$(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
+  C =			c
+  C_COMPILER =		$(CROSS_COMPILE)gcc
+  C_FLAGS =		$(COMPILE_OPTS)
+  CPP =			cpp
++ CPLUSPLUS_COMPILER =	$(CROSS_COMPILE)g++
+  CPLUSPLUS_FLAGS =	$(COMPILE_OPTS) -Wall -DBSD=1
+  OBJ =			o
++ LINK =			$(CROSS_COMPILE)g++ -o
++ LINK_OPTS =		
+  CONSOLE_LINK_OPTS =	$(LINK_OPTS)
++ LIBRARY_LINK =		$(CROSS_COMPILE)ar cr 
+  LIBRARY_LINK_OPTS =	$(LINK_OPTS)
+  LIB_SUFFIX =			a
+  LIBS_FOR_CONSOLE_APPLICATION =
diff --git a/groupsock/GroupsockHelper.cpp b/groupsock/GroupsockHelper.cpp
index 6deaadc..c7c8098 100644
--- a/groupsock/GroupsockHelper.cpp
+++ b/groupsock/GroupsockHelper.cpp
@@ -469,16 +469,7 @@ Boolean socketLeaveGroup(UsageEnvironment&, int socket,
 // The source-specific join/leave operations require special setsockopt()
 // commands, and a special structure (ip_mreq_source).  If the include files
 // didn't define these, we do so here:
-#if !defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(__CYGWIN32__)
-// NOTE TO CYGWIN DEVELOPERS:
-//    The "defined(__CYGWIN32__)" test was added above, because - as of January 2007 - the Cygwin header files
-//    define IP_ADD_SOURCE_MEMBERSHIP (and IP_DROP_SOURCE_MEMBERSHIP), but do not define ip_mreq_source.
-//    This has been acknowledged as a bug (see <http://cygwin.com/ml/cygwin/2007-01/msg00516.html>), but it's
-//    not clear when it is going to be fixed.  When the Cygwin header files finally define "ip_mreq_source",
-//    this code will no longer compile, due to "ip_mreq_source" being defined twice.  When this happens, please
-//    let us know, by sending email to the "live-devel" mailing list.
-//    (See <http://lists.live555.com/mailman/listinfo/live-devel/> to subscribe to that mailing list.)
-// END NOTE TO CYGWIN DEVELOPERS
+#if !defined(IP_ADD_SOURCE_MEMBERSHIP)
 struct ip_mreq_source {
   struct  in_addr imr_multiaddr;  /* IP multicast address of group */
   struct  in_addr imr_sourceaddr; /* IP address of source */
diff --git a/groupsock/include/groupsock_version.hh b/groupsock/include/groupsock_version.hh
index 857f734..c28bcf3 100644
--- a/groupsock/include/groupsock_version.hh
+++ b/groupsock/include/groupsock_version.hh
@@ -4,7 +4,7 @@
 #ifndef _GROUPSOCK_VERSION_HH
 #define _GROUPSOCK_VERSION_HH
 
-#define GROUPSOCK_LIBRARY_VERSION_STRING	"2010.02.10"
-#define GROUPSOCK_LIBRARY_VERSION_INT		1265760000
+#define GROUPSOCK_LIBRARY_VERSION_STRING	"2010.04.09"
+#define GROUPSOCK_LIBRARY_VERSION_INT		1270771200
 
 #endif
diff --git a/liveMedia/AMRAudioRTPSource.cpp b/liveMedia/AMRAudioRTPSource.cpp
index d63a92d..01b2b2e 100644
--- a/liveMedia/AMRAudioRTPSource.cpp
+++ b/liveMedia/AMRAudioRTPSource.cpp
@@ -67,7 +67,7 @@ private:
   unsigned char fILL, fILP;
   unsigned fTOCSize;
   unsigned char* fTOC;
-  unsigned fFrameIndex, fNumSuccessiveSyncedPackets;
+  unsigned fFrameIndex;
   Boolean fIsSynchronized;
 };
 
@@ -216,8 +216,7 @@ RawAMRRTPSource
                          new AMRBufferedPacketFactory),
   fIsWideband(isWideband), fIsOctetAligned(isOctetAligned),
   fIsInterleaved(isInterleaved), fCRCsArePresent(CRCsArePresent),
-  fILL(0), fILP(0), fTOCSize(0), fTOC(NULL), fFrameIndex(0),
-    fNumSuccessiveSyncedPackets(0), fIsSynchronized(false) {
+  fILL(0), fILP(0), fTOCSize(0), fTOC(NULL), fFrameIndex(0), fIsSynchronized(False) {
 }
 
 RawAMRRTPSource::~RawAMRRTPSource() {
@@ -240,13 +239,6 @@ Boolean RawAMRRTPSource
   unsigned char* headerStart = packet->data();
   unsigned packetSize = packet->dataSize();
 
-  // First, check whether this packet's RTP timestamp is synchronized:
-  if (RTPSource::hasBeenSynchronizedUsingRTCP()) {
-    ++fNumSuccessiveSyncedPackets;
-  } else {
-    fNumSuccessiveSyncedPackets = 0;
-  }
-
   // There's at least a 1-byte header, containing the CMR:
   if (packetSize < 1) return False;
   resultSpecialHeaderSize = 1;
@@ -427,6 +419,8 @@ private:
   u_int16_t fLastPacketSeqNumForGroup;
   unsigned char* fInputBuffer;
   struct timeval fLastRetrievedPresentationTime;
+  unsigned fNumSuccessiveSyncedFrames;
+  unsigned char fILL;
 };
 
 
@@ -517,7 +511,7 @@ AMRDeinterleavingBuffer
   : fNumChannels(numChannels), fMaxInterleaveGroupSize(maxInterleaveGroupSize),
     fIncomingBankId(0), fIncomingBinMax(0),
     fOutgoingBinMax(0), fNextOutgoingBin(0),
-    fHaveSeenPackets(False) {
+    fHaveSeenPackets(False), fNumSuccessiveSyncedFrames(0), fILL(0) {
   // Use two banks of descriptors - one for incoming, one for outgoing
   fFrames[0] = new FrameDescriptor[fMaxInterleaveGroupSize];
   fFrames[1] = new FrameDescriptor[fMaxInterleaveGroupSize];
@@ -532,16 +526,16 @@ AMRDeinterleavingBuffer::~AMRDeinterleavingBuffer() {
 void AMRDeinterleavingBuffer
 ::deliverIncomingFrame(unsigned frameSize, RawAMRRTPSource* source,
 		       struct timeval presentationTime) {
-  unsigned char const ILL = source->ILL();
+  fILL = source->ILL();
   unsigned char const ILP = source->ILP();
   unsigned frameIndex = source->frameIndex();
   unsigned short packetSeqNum = source->curPacketRTPSeqNum();
 
   // First perform a sanity check on the parameters:
   // (This is overkill, as the source should have already done this.)
-  if (ILP > ILL || frameIndex == 0) {
+  if (ILP > fILL || frameIndex == 0) {
 #ifdef DEBUG
-    fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, ILL, ILP, frameIndex);
+    fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, fILL, ILP, frameIndex);
 #endif
     abort();
   }
@@ -559,7 +553,7 @@ void AMRDeinterleavingBuffer
 
   // The input "presentationTime" was that of the first frame-block in this
   // packet.  Update it for the current frame:
-  unsigned uSecIncrement = frameBlockIndex*(ILL+1)*uSecsPerFrame;
+  unsigned uSecIncrement = frameBlockIndex*(fILL+1)*uSecsPerFrame;
   presentationTime.tv_usec += uSecIncrement;
   presentationTime.tv_sec += presentationTime.tv_usec/1000000;
   presentationTime.tv_usec = presentationTime.tv_usec%1000000;
@@ -572,7 +566,7 @@ void AMRDeinterleavingBuffer
     fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): new interleave group\n");
 #endif
     fHaveSeenPackets = True;
-    fLastPacketSeqNumForGroup = packetSeqNum + ILL - ILP;
+    fLastPacketSeqNumForGroup = packetSeqNum + fILL - ILP;
 
     // Switch the incoming and outgoing banks:
     fIncomingBankId ^= 1;
@@ -584,7 +578,7 @@ void AMRDeinterleavingBuffer
 
   // Now move the incoming frame into the appropriate bin:
   unsigned const binNumber
-    = ((ILP + frameBlockIndex*(ILL+1))*fNumChannels + frameWithinFrameBlock)
+    = ((ILP + frameBlockIndex*(fILL+1))*fNumChannels + frameWithinFrameBlock)
       % fMaxInterleaveGroupSize; // the % is for sanity
 #ifdef DEBUG
   fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): frameIndex %d (%d,%d) put in bank %d, bin %d (%d): size %d, header 0x%02x, presentationTime %lu.%06ld\n", frameIndex, frameBlockIndex, frameWithinFrameBlock, fIncomingBankId, binNumber, fMaxInterleaveGroupSize, frameSize, frameHeader, presentationTime.tv_sec, presentationTime.tv_usec);
@@ -595,7 +589,7 @@ void AMRDeinterleavingBuffer
   inBin.frameSize = frameSize;
   inBin.frameHeader = frameHeader;
   inBin.presentationTime = presentationTime;
-  inBin.fIsSynchronized = ((RTPSource*)source)->hasBeenSynchronizedUsingRTCP();
+  inBin.fIsSynchronized = ((RTPSource*)source)->RTPSource::hasBeenSynchronizedUsingRTCP();
 
   if (curBuffer == NULL) curBuffer = createNewBuffer();
   fInputBuffer = curBuffer;
@@ -618,7 +612,17 @@ Boolean AMRDeinterleavingBuffer
   unsigned char* fromPtr = outBin.frameData;
   unsigned char fromSize = outBin.frameSize;
   outBin.frameSize = 0; // for the next time this bin is used
-  resultIsSynchronized = outBin.fIsSynchronized;
+  resultIsSynchronized = False; // by default; can be changed by:
+  if (outBin.fIsSynchronized) {
+    // Don't consider the outgoing frame to be synchronized until we've received at least a complete interleave cycle of
+    // synchronized frames.  This ensures that the receiver will be getting all synchronized frames from now on.
+    if (++fNumSuccessiveSyncedFrames > fILL) {
+      resultIsSynchronized = True;
+      fNumSuccessiveSyncedFrames = fILL+1; // prevents overflow
+    }
+  } else {
+    fNumSuccessiveSyncedFrames = 0;
+  } 
 
   // Check whether this frame is missing; if so, return a FT_NO_DATA frame:
   if (fromSize == 0) {
diff --git a/liveMedia/DigestAuthentication.cpp b/liveMedia/DigestAuthentication.cpp
index d39c969..9bf99fe 100644
--- a/liveMedia/DigestAuthentication.cpp
+++ b/liveMedia/DigestAuthentication.cpp
@@ -30,6 +30,10 @@ Authenticator::Authenticator() {
   assign(NULL, NULL, NULL, NULL, False);
 }
 
+Authenticator::Authenticator(char const* username, char const* password) {
+  setUsernameAndPassword(username, password);
+}
+
 Authenticator::Authenticator(const Authenticator& orig) {
   assign(orig.realm(), orig.nonce(), orig.username(), orig.password(),
 	 orig.fPasswordIsMD5);
diff --git a/liveMedia/MPEG2IndexFromTransportStream.cpp b/liveMedia/MPEG2IndexFromTransportStream.cpp
index ba0d8a2..238b001 100644
--- a/liveMedia/MPEG2IndexFromTransportStream.cpp
+++ b/liveMedia/MPEG2IndexFromTransportStream.cpp
@@ -277,11 +277,15 @@ void MPEG2IFrameIndexFromTransportStream::handleInputClosure1() {
 
 void MPEG2IFrameIndexFromTransportStream
 ::analyzePAT(unsigned char* pkt, unsigned size) {
-  // Get the PMT_PID (we assume that's there just 1 program):
-  if (size < 16) return; // table too small
-  u_int16_t program_number = (pkt[9]<<8) | pkt[10];
-  if (program_number != 0) {
-    fPMT_PID = ((pkt[11]&0x1F)<<8) | pkt[12];
+  // Get the PMT_PID:
+  while (size >= 17) { // The table is large enough
+    u_int16_t program_number = (pkt[9]<<8) | pkt[10];
+    if (program_number != 0) {
+      fPMT_PID = ((pkt[11]&0x1F)<<8) | pkt[12];
+      return;
+    }
+
+    pkt += 4; size -= 4;
   }
 }
 
diff --git a/liveMedia/MPEG2TransportFileServerMediaSubsession.cpp b/liveMedia/MPEG2TransportFileServerMediaSubsession.cpp
index 8cc10df..eb7f9e6 100644
--- a/liveMedia/MPEG2TransportFileServerMediaSubsession.cpp
+++ b/liveMedia/MPEG2TransportFileServerMediaSubsession.cpp
@@ -118,7 +118,9 @@ MPEG2TransportFileServerMediaSubsession
 void MPEG2TransportFileServerMediaSubsession
 ::startStream(unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler,
 	      void* rtcpRRHandlerClientData, unsigned short& rtpSeqNum,
-	      unsigned& rtpTimestamp) {
+	      unsigned& rtpTimestamp,
+	      ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+	      void* serverRequestAlternativeByteHandlerClientData) {
   if (fIndexFile != NULL) { // we support 'trick play'
     ClientTrickPlayState* client = lookupClient(clientSessionId);
     if (client != NULL && client->areChangingScale()) {
@@ -134,7 +136,8 @@ void MPEG2TransportFileServerMediaSubsession
   // Call the original, default version of this routine:
   OnDemandServerMediaSubsession::startStream(clientSessionId, streamToken,
 					     rtcpRRHandler, rtcpRRHandlerClientData,
-					     rtpSeqNum, rtpTimestamp);
+					     rtpSeqNum, rtpTimestamp,
+					     serverRequestAlternativeByteHandler, serverRequestAlternativeByteHandlerClientData);
 }
 
 void MPEG2TransportFileServerMediaSubsession
diff --git a/liveMedia/Makefile.tail b/liveMedia/Makefile.tail
index 79badcc..ac9eaae 100644
--- a/liveMedia/Makefile.tail
+++ b/liveMedia/Makefile.tail
@@ -237,7 +237,7 @@ include/RTCP.hh:		include/RTPSink.hh include/RTPSource.hh
 rtcp_from_spec.$(C):	rtcp_from_spec.h
 RTSPServer.$(CPP):	include/RTSPServer.hh include/RTSPCommon.hh
 include/RTSPServer.hh:		include/ServerMediaSession.hh include/DigestAuthentication.hh include/RTSPCommon.hh
-include/ServerMediaSession.hh:	include/Media.hh include/RTSPCommon.hh
+include/ServerMediaSession.hh:	include/Media.hh include/RTPInterface.hh
 RTSPOverHTTPServer.$(CPP):	include/RTSPOverHTTPServer.hh include/RTSPCommon.hh
 include/RTSPOverHTTPServer.hh:	include/Media.hh
 RTSPClient.$(CPP):	include/RTSPClient.hh  include/RTSPCommon.hh include/Base64.hh include/Locale.hh our_md5.h
@@ -276,7 +276,7 @@ ADTSAudioFileServerMediaSubsession.$(CPP):	include/ADTSAudioFileServerMediaSubse
 include/ADTSAudioFileServerMediaSubsession.hh:	include/FileServerMediaSubsession.hh
 DVVideoFileServerMediaSubsession.$(CPP):	include/DVVideoFileServerMediaSubsession.hh include/DVVideoRTPSink.hh include/ByteStreamFileSource.hh include/DVVideoStreamFramer.hh
 include/DVVideoFileServerMediaSubsession.hh:	include/FileServerMediaSubsession.hh
-QuickTimeFileSink.$(CPP):	include/QuickTimeFileSink.hh include/OutputFile.hh include/QuickTimeGenericRTPSource.hh include/H263plusVideoRTPSource.hh include/MPEG4GenericRTPSource.hh include/MPEG4LATMAudioRTPSource.hh
+QuickTimeFileSink.$(CPP):	include/QuickTimeFileSink.hh include/InputFile.hh include/OutputFile.hh include/QuickTimeGenericRTPSource.hh include/H263plusVideoRTPSource.hh include/MPEG4GenericRTPSource.hh include/MPEG4LATMAudioRTPSource.hh
 include/QuickTimeFileSink.hh:	include/MediaSession.hh
 QuickTimeGenericRTPSource.$(CPP):	include/QuickTimeGenericRTPSource.hh
 include/QuickTimeGenericRTPSource.hh:	include/MultiFramedRTPSource.hh
diff --git a/liveMedia/MediaSession.cpp b/liveMedia/MediaSession.cpp
index 955ca9a..6a598d4 100644
--- a/liveMedia/MediaSession.cpp
+++ b/liveMedia/MediaSession.cpp
@@ -21,9 +21,6 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 
 #include "liveMedia.hh"
 #include "Locale.hh"
-#ifdef SUPPORT_REAL_RTSP
-#include "../RealRTSP/include/RealRTSP.hh"
-#endif
 #include "GroupsockHelper.hh"
 #include <ctype.h>
 
@@ -65,9 +62,6 @@ MediaSession::MediaSession(UsageEnvironment& env)
     fConnectionEndpointName(NULL), fMaxPlayStartTime(0.0f), fMaxPlayEndTime(0.0f),
     fScale(1.0f), fMediaSessionType(NULL), fSessionName(NULL), fSessionDescription(NULL),
     fControlPath(NULL) {
-#ifdef SUPPORT_REAL_RTSP
-  RealInitSDPAttributes(this);
-#endif
   fSourceFilterAddr.s_addr = 0;
 
   // Get our host name, and use this for the RTCP CNAME:
@@ -91,9 +85,6 @@ MediaSession::~MediaSession() {
   delete[] fSessionName;
   delete[] fSessionDescription;
   delete[] fControlPath;
-#ifdef SUPPORT_REAL_RTSP
-  RealReclaimSDPAttributes(this);
-#endif
 }
 
 Boolean MediaSession::isMediaSession() const {
@@ -123,9 +114,6 @@ Boolean MediaSession::initializeWithSDP(char const* sdpDescription) {
     if (parseSDPAttribute_range(sdpLine)) continue;
     if (parseSDPAttribute_type(sdpLine)) continue;
     if (parseSDPAttribute_source_filter(sdpLine)) continue;
-#ifdef SUPPORT_REAL_RTSP
-    if (RealParseSDPAttributes(this, sdpLine)) continue;
-#endif
   }
 
   while (sdpLine != NULL) {
@@ -219,9 +207,6 @@ Boolean MediaSession::initializeWithSDP(char const* sdpDescription) {
       if (subsession->parseSDPAttribute_source_filter(sdpLine)) continue;
       if (subsession->parseSDPAttribute_x_dimensions(sdpLine)) continue;
       if (subsession->parseSDPAttribute_framerate(sdpLine)) continue;
-#ifdef SUPPORT_REAL_RTSP
-      if (RealParseSDPAttributes(subsession, sdpLine)) continue;
-#endif
 
       // (Later, check for malformed lines, and other valid SDP lines#####)
     }
@@ -556,9 +541,6 @@ MediaSubsession::MediaSubsession(MediaSession& parent)
     fRTPSocket(NULL), fRTCPSocket(NULL),
     fRTPSource(NULL), fRTCPInstance(NULL), fReadSource(NULL) {
   rtpInfo.seqNum = 0; rtpInfo.timestamp = 0; rtpInfo.infoIsNew = False;
-#ifdef SUPPORT_REAL_RTSP
-  RealInitSDPAttributes(this);
-#endif
 }
 
 MediaSubsession::~MediaSubsession() {
@@ -569,9 +551,6 @@ MediaSubsession::~MediaSubsession() {
   delete[] fControlPath; delete[] fConfig; delete[] fMode; delete[] fSpropParameterSets;
 
   delete fNext;
-#ifdef SUPPORT_REAL_RTSP
-  RealReclaimSDPAttributes(this);
-#endif
 }
 
 double MediaSubsession::playStartTime() const {
@@ -635,6 +614,7 @@ Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {
       HashTable* socketHashTable = HashTable::create(ONE_WORD_HASH_KEYS);
       if (socketHashTable == NULL) break;
       Boolean success = False;
+      NoReuse dummy; // ensures that our new ephemeral port number won't be one that's already in use
 
       while (1) {
 	// Create a new socket:
@@ -848,16 +828,6 @@ Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {
 						 fRTPTimestampFrequency,
 						 mimeType);
 	delete[] mimeType;
-#ifdef SUPPORT_REAL_RTSP
-      } else if (strcmp(fCodecName, "X-PN-REALAUDIO") == 0 ||
-		 strcmp(fCodecName, "X-PN-MULTIRATE-REALAUDIO-LIVE") == 0 ||
-		 strcmp(fCodecName, "X-PN-REALVIDEO") == 0 ||
-		 strcmp(fCodecName, "X-PN-MULTIRATE-REALVIDEO-LIVE") == 0) {
-	// A RealNetworks 'RDT' stream (*not* a RTP stream)
-	fReadSource = RealRDTSource::createNew(env());
-	fRTPSource = NULL; // Note!
-	parentSession().isRealNetworksRDT = True;
-#endif
       } else if (  strcmp(fCodecName, "PCMU") == 0 // PCM u-law audio
 		   || strcmp(fCodecName, "GSM") == 0 // GSM audio
 		   || strcmp(fCodecName, "PCMA") == 0 // PCM a-law audio
diff --git a/liveMedia/OnDemandServerMediaSubsession.cpp b/liveMedia/OnDemandServerMediaSubsession.cpp
index 6df61f5..2524250 100644
--- a/liveMedia/OnDemandServerMediaSubsession.cpp
+++ b/liveMedia/OnDemandServerMediaSubsession.cpp
@@ -106,7 +106,9 @@ public:
   virtual ~StreamState();
 
   void startPlaying(Destinations* destinations,
-		    TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData);
+		    TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData,
+		    ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+                    void* serverRequestAlternativeByteHandlerClientData);
   void pause();
   void endPlaying(Destinations* destinations);
   void reclaim();
@@ -257,13 +259,16 @@ void OnDemandServerMediaSubsession::startStream(unsigned clientSessionId,
 						TaskFunc* rtcpRRHandler,
 						void* rtcpRRHandlerClientData,
 						unsigned short& rtpSeqNum,
-						unsigned& rtpTimestamp) {
+						unsigned& rtpTimestamp,
+						ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+						void* serverRequestAlternativeByteHandlerClientData) {
   StreamState* streamState = (StreamState*)streamToken;
   Destinations* destinations
     = (Destinations*)(fDestinationsHashTable->Lookup((char const*)clientSessionId));
   if (streamState != NULL) {
     streamState->startPlaying(destinations,
-			      rtcpRRHandler, rtcpRRHandlerClientData);
+			      rtcpRRHandler, rtcpRRHandlerClientData,
+			      serverRequestAlternativeByteHandler, serverRequestAlternativeByteHandlerClientData);
     if (streamState->rtpSink() != NULL) {
       rtpSeqNum = streamState->rtpSink()->currentSeqNo();
       rtpTimestamp = streamState->rtpSink()->presetNextTimestamp();
@@ -434,7 +439,9 @@ StreamState::~StreamState() {
 
 void StreamState
 ::startPlaying(Destinations* dests,
-	       TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData) {
+	       TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData,
+	       ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+	       void* serverRequestAlternativeByteHandlerClientData) {
   if (dests == NULL) return;
   if (!fAreCurrentlyPlaying && fMediaSource != NULL) {
     if (fRTPSink != NULL) {
@@ -459,6 +466,7 @@ void StreamState
     // Change RTP and RTCP to use the TCP socket instead of UDP:
     if (fRTPSink != NULL) {
       fRTPSink->addStreamSocket(dests->tcpSocketNum, dests->rtpChannelId);
+      fRTPSink->setServerRequestAlternativeByteHandler(serverRequestAlternativeByteHandler, serverRequestAlternativeByteHandlerClientData);
     }
     if (fRTCPInstance != NULL) {
       fRTCPInstance->addStreamSocket(dests->tcpSocketNum, dests->rtcpChannelId);
diff --git a/liveMedia/PassiveServerMediaSubsession.cpp b/liveMedia/PassiveServerMediaSubsession.cpp
index 7c87984..1f83cc1 100644
--- a/liveMedia/PassiveServerMediaSubsession.cpp
+++ b/liveMedia/PassiveServerMediaSubsession.cpp
@@ -133,7 +133,9 @@ void PassiveServerMediaSubsession::startStream(unsigned /*clientSessionId*/,
 					       TaskFunc* /*rtcpRRHandler*/,
 					       void* /*rtcpRRHandlerClientData*/,
 					       unsigned short& rtpSeqNum,
-					       unsigned& rtpTimestamp) {
+					       unsigned& rtpTimestamp,
+					       ServerRequestAlternativeByteHandler* /*serverRequestAlternativeByteHandler*/,
+					       void* /*serverRequestAlternativeByteHandlerClientData*/) {
   // Note: We don't set a RTCP RR handler, because (i) we're called potentially
   // many times on the same "RTCPInstance", and (ii) the "RTCPInstance" remains
   // in existence after "deleteStream()" is called.
diff --git a/liveMedia/QuickTimeFileSink.cpp b/liveMedia/QuickTimeFileSink.cpp
index 5ea16a4..1e7724b 100644
--- a/liveMedia/QuickTimeFileSink.cpp
+++ b/liveMedia/QuickTimeFileSink.cpp
@@ -21,6 +21,7 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 #include "QuickTimeFileSink.hh"
 #include "QuickTimeGenericRTPSource.hh"
 #include "GroupsockHelper.hh"
+#include "InputFile.hh"
 #include "OutputFile.hh"
 #include "H263plusVideoRTPSource.hh" // for the special header
 #include "MPEG4GenericRTPSource.hh" //for "samplingFrequencyFromAudioSpecificConfig()"
@@ -31,24 +32,26 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 
 #define fourChar(x,y,z,w) ( ((x)<<24)|((y)<<16)|((z)<<8)|(w) )
 
+#define H264_IDR_FRAME 0x65  //bit 8 == 0, bits 7-6 (ref) == 3, bits 5-0 (type) == 5
+
 ////////// SubsessionIOState, ChunkDescriptor ///////////
 // A structure used to represent the I/O state of each input 'subsession':
 
 class ChunkDescriptor {
 public:
-  ChunkDescriptor(unsigned offsetInFile, unsigned size,
+  ChunkDescriptor(int64_t offsetInFile, unsigned size,
 		  unsigned frameSize, unsigned frameDuration,
 		  struct timeval presentationTime);
   virtual ~ChunkDescriptor();
 
-  ChunkDescriptor* extendChunk(unsigned newOffsetInFile, unsigned newSize,
+  ChunkDescriptor* extendChunk(int64_t newOffsetInFile, unsigned newSize,
 			       unsigned newFrameSize,
 			       unsigned newFrameDuration,
 			       struct timeval newPresentationTime);
       // this may end up allocating a new chunk instead
 public:
   ChunkDescriptor* fNextChunk;
-  unsigned fOffsetInFile;
+  int64_t fOffsetInFile;
   unsigned fNumFrames;
   unsigned fFrameSize;
   unsigned fFrameDuration;
@@ -83,15 +86,26 @@ private:
   unsigned fBytesInUse;
 };
 
-// A 64-bit counter, used below:
+class SyncFrame {
+public:
+  SyncFrame(unsigned frameNum);
+  virtual ~SyncFrame();
+
+public:
+  class SyncFrame *nextSyncFrame;
+  unsigned sfFrameNum;  
+};
 
+// A 64-bit counter, used below:
 class Count64 {
 public:
-  Count64() { hi = lo = 0; }
+  Count64()
+    : hi(0), lo(0) {
+  }
 
   void operator+=(unsigned arg);
 
-  unsigned hi, lo; // each 32 bits
+  u_int32_t hi, lo;
 };
 
 class SubsessionIOState {
@@ -148,13 +162,14 @@ public:
   unsigned fQTTotNumSamples;
   unsigned fQTDurationM; // in media time units
   unsigned fQTDurationT; // in track time units
-  unsigned fTKHD_durationPosn;
+  int64_t fTKHD_durationPosn;
       // position of the duration in the output 'tkhd' atom
   unsigned fQTInitialOffsetDuration;
       // if there's a pause at the beginning
 
   ChunkDescriptor *fHeadChunk, *fTailChunk;
   unsigned fNumChunks;
+  SyncFrame *fHeadSyncFrame, *fTailSyncFrame;
 
   // Counters to be used in the hint track's 'udta'/'hinf' atom;
   struct hinf {
@@ -179,7 +194,7 @@ private:
   // used by the above two routines:
   unsigned useFrame1(unsigned sourceDataSize,
 		     struct timeval presentationTime,
-		     unsigned frameDuration, unsigned destFileOffset);
+		     unsigned frameDuration, int64_t destFileOffset);
       // returns the number of samples in this data
 
 private:
@@ -187,7 +202,7 @@ private:
   struct {
     unsigned frameSize;
     struct timeval presentationTime;
-    unsigned destFileOffset; // used for non-hint tracks only
+    int64_t destFileOffset; // used for non-hint tracks only
 
     // The remaining fields are used for hint tracks only:
     unsigned startSampleNumber;
@@ -292,8 +307,10 @@ QuickTimeFileSink::QuickTimeFileSink(UsageEnvironment& env,
   // Begin by writing a "mdat" atom at the start of the file.
   // (Later, when we've finished copying data to the file, we'll come
   // back and fill in its size.)
-  fMDATposition = ftell(fOutFid);
-  addAtomHeader("mdat");
+  fMDATposition = TellFile64(fOutFid);
+  addAtomHeader64("mdat");
+  // add 64Bit offset
+  fMDATposition += 8;
 }
 
 QuickTimeFileSink::~QuickTimeFileSink() {
@@ -455,8 +472,8 @@ void QuickTimeFileSink::completeOutputFile() {
 
   // Begin by filling in the initial "mdat" atom with the current
   // file size:
-  unsigned curFileSize = ftell(fOutFid);
-  setWord(fMDATposition, curFileSize);
+  int64_t curFileSize = TellFile64(fOutFid);
+  setWord64(fMDATposition, (u_int64_t)curFileSize);
 
   // Then, note the time of the first received data:
   MediaSubsessionIterator iter(fInputSession);
@@ -508,8 +525,9 @@ SubsessionIOState::SubsessionIOState(QuickTimeFileSink& sink,
 				     MediaSubsession& subsession)
   : fHintTrackForUs(NULL), fTrackHintedByUs(NULL),
     fOurSink(sink), fOurSubsession(subsession),
-    fLastPacketRTPSeqNum(0), fHaveBeenSynced(False), fQTTotNumSamples(0),
-    fHeadChunk(NULL), fTailChunk(NULL), fNumChunks(0) {
+    fLastPacketRTPSeqNum(0), fHaveBeenSynced(False), fQTTotNumSamples(0), 
+    fHeadChunk(NULL), fTailChunk(NULL), fNumChunks(0),
+    fHeadSyncFrame(NULL), fTailSyncFrame(NULL) {
   fTrackID = ++fCurrentTrackNumber;
 
   fBuffer = new SubsessionBuffer(fOurSink.fBufferSize);
@@ -526,7 +544,7 @@ SubsessionIOState::SubsessionIOState(QuickTimeFileSink& sink,
 
 SubsessionIOState::~SubsessionIOState() {
   delete fBuffer; delete fPrevBuffer;
-  delete fHeadChunk;
+  delete fHeadChunk; delete fHeadSyncFrame;
 }
 
 Boolean SubsessionIOState::setQTstate() {
@@ -750,7 +768,7 @@ void SubsessionIOState::useFrame(SubsessionBuffer& buffer) {
   unsigned char* const frameSource = buffer.dataStart();
   unsigned const frameSize = buffer.bytesInUse();
   struct timeval const& presentationTime = buffer.presentationTime();
-  unsigned const destFileOffset = ftell(fOurSink.fOutFid);
+  int64_t const destFileOffset = TellFile64(fOurSink.fOutFid);
   unsigned sampleNumberOfFrameStart = fQTTotNumSamples + 1;
   Boolean avcHack = fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_avc1;
 
@@ -784,6 +802,16 @@ void SubsessionIOState::useFrame(SubsessionBuffer& buffer) {
       sampleNumberOfFrameStart = fQTTotNumSamples + 1;
     }
 
+    if (avcHack && (*frameSource == H264_IDR_FRAME)) {
+      SyncFrame* newSyncFrame = new SyncFrame(fQTTotNumSamples + 1);
+      if (fTailSyncFrame == NULL) {
+        fHeadSyncFrame = newSyncFrame;
+      } else {
+        fTailSyncFrame->nextSyncFrame = newSyncFrame;
+      }
+      fTailSyncFrame = newSyncFrame;
+    }
+
     // Remember the current frame for next time:
     fPrevFrameState.frameSize = frameSize;
     fPrevFrameState.presentationTime = presentationTime;
@@ -854,7 +882,7 @@ void SubsessionIOState::useFrameForHinting(unsigned frameSize,
       }
     }
 
-    unsigned const hintSampleDestFileOffset = ftell(fOurSink.fOutFid);
+    int64_t const hintSampleDestFileOffset = TellFile64(fOurSink.fOutFid);
 
     unsigned const maxPacketSize = 1450;
     unsigned short numPTEntries
@@ -1009,7 +1037,7 @@ void SubsessionIOState::useFrameForHinting(unsigned frameSize,
 unsigned SubsessionIOState::useFrame1(unsigned sourceDataSize,
 				      struct timeval presentationTime,
 				      unsigned frameDuration,
-				      unsigned destFileOffset) {
+				      int64_t destFileOffset) {
   // Figure out the actual frame size for this data:
   unsigned frameSize = fQTBytesPerFrame;
   if (frameSize == 0) {
@@ -1054,6 +1082,15 @@ Boolean SubsessionIOState::syncOK(struct timeval presentationTime) {
     if (!fHaveBeenSynced) {
       // We weren't synchronized before
       if (fOurSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP()) {
+	// H264 ?
+	if (fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_avc1) {
+	  // special case: audio + H264 video: wait until audio is in sync
+	  if ((s.fNumSubsessions == 2) && (s.fNumSyncedSubsessions < (s.fNumSubsessions - 1))) return False;
+
+	  // if audio is in sync, wait for the next IDR frame to start
+	  unsigned char* const frameSource = fBuffer->dataStart();
+	  if (*frameSource != H264_IDR_FRAME) return False;
+	}
 	// But now we are
 	fHaveBeenSynced = True;
 	fSyncTime = presentationTime;
@@ -1079,6 +1116,14 @@ void SubsessionIOState::setHintTrack(SubsessionIOState* hintedTrack,
   if (hintTrack != NULL) hintTrack->fTrackHintedByUs = hintedTrack;
 }
 
+SyncFrame::SyncFrame(unsigned frameNum)
+  : nextSyncFrame(NULL), sfFrameNum(frameNum) {
+}  
+
+SyncFrame::~SyncFrame() {
+  delete nextSyncFrame;
+}
+
 void Count64::operator+=(unsigned arg) {
   unsigned newLo = lo + arg;
   if (newLo < lo) { // lo has overflowed
@@ -1088,7 +1133,7 @@ void Count64::operator+=(unsigned arg) {
 }
 
 ChunkDescriptor
-::ChunkDescriptor(unsigned offsetInFile, unsigned size,
+::ChunkDescriptor(int64_t offsetInFile, unsigned size,
 		  unsigned frameSize, unsigned frameDuration,
 		  struct timeval presentationTime)
   : fNextChunk(NULL), fOffsetInFile(offsetInFile),
@@ -1102,7 +1147,7 @@ ChunkDescriptor::~ChunkDescriptor() {
 }
 
 ChunkDescriptor* ChunkDescriptor
-::extendChunk(unsigned newOffsetInFile, unsigned newSize,
+::extendChunk(int64_t newOffsetInFile, unsigned newSize,
 	      unsigned newFrameSize, unsigned newFrameDuration,
 	      struct timeval newPresentationTime) {
   // First, check whether the new space is just at the end of this
@@ -1130,6 +1175,15 @@ ChunkDescriptor* ChunkDescriptor
 
 ////////// QuickTime-specific implementation //////////
 
+unsigned QuickTimeFileSink::addWord64(u_int64_t word) {
+  addByte((unsigned char)(word>>56)); addByte((unsigned char)(word>>48));
+  addByte((unsigned char)(word>>40)); addByte((unsigned char)(word>>32));
+  addByte((unsigned char)(word>>24)); addByte((unsigned char)(word>>16));
+  addByte((unsigned char)(word>>8)); addByte((unsigned char)(word));
+
+  return 8;
+}
+
 unsigned QuickTimeFileSink::addWord(unsigned word) {
   addByte(word>>24); addByte(word>>16);
   addByte(word>>8); addByte(word);
@@ -1188,11 +1242,37 @@ unsigned QuickTimeFileSink::addAtomHeader(char const* atomName) {
   return 8;
 }
 
-void QuickTimeFileSink::setWord(unsigned filePosn, unsigned size) {
+unsigned QuickTimeFileSink::addAtomHeader64(char const* atomName) {
+  // Output 64Bit size marker
+  addWord(1);
+
+  // Output the 4-byte atom name:
+  add4ByteString(atomName);
+
+  addWord64(0);
+
+  return 16;
+}
+
+void QuickTimeFileSink::setWord(int64_t filePosn, unsigned size) {
   do {
-    if (fseek(fOutFid, filePosn, SEEK_SET) < 0) break;
+    if (SeekFile64(fOutFid, filePosn, SEEK_SET) < 0) break;
     addWord(size);
-    if (fseek(fOutFid, 0, SEEK_END) < 0) break; // go back to where we were
+    if (SeekFile64(fOutFid, 0, SEEK_END) < 0) break; // go back to where we were
+
+    return;
+  } while (0);
+
+  // One of the fseek()s failed, probable because we're not a seekable file
+  envir() << "QuickTimeFileSink::setWord(): fseek failed (err "
+	  << envir().getErrno() << ")\n";
+}
+
+void QuickTimeFileSink::setWord64(int64_t filePosn, u_int64_t size) {
+  do {
+    if (SeekFile64(fOutFid, filePosn, SEEK_SET) < 0) break;
+    addWord64(size);
+    if (SeekFile64(fOutFid, 0, SEEK_END) < 0) break; // go back to where we were
 
     return;
   } while (0);
@@ -1206,7 +1286,7 @@ void QuickTimeFileSink::setWord(unsigned filePosn, unsigned size) {
 
 #define addAtom(name) \
     unsigned QuickTimeFileSink::addAtom_##name() { \
-    unsigned initFilePosn = ftell(fOutFid); \
+    int64_t initFilePosn = TellFile64(fOutFid); \
     unsigned size = addAtomHeader("" #name "")
 
 #define addAtomEnd \
@@ -1273,7 +1353,7 @@ addAtom(mvhd);
   size += addWord(movieTimeScale()); // Time scale
 
   unsigned const duration = fMaxTrackDurationM;
-  fMVHD_durationPosn = ftell(fOutFid);
+  fMVHD_durationPosn = TellFile64(fOutFid);
   size += addWord(duration); // Duration
 
   size += addWord(0x00010000); // Preferred rate
@@ -1327,7 +1407,7 @@ addAtom(tkhd);
   size += addWord(0x00000000); // Reserved
 
   unsigned const duration = fCurrentIOState->fQTDurationM; // movie units
-  fCurrentIOState->fTKHD_durationPosn = ftell(fOutFid);
+  fCurrentIOState->fTKHD_durationPosn = TellFile64(fOutFid);
   size += addWord(duration); // Duration
   size += addZeroWords(3); // Reserved+Layer+Alternate grp
   size += addWord(0x01000000); // Volume + Reserved
@@ -1366,7 +1446,7 @@ addAtom(elst);
 
   // Add a dummy "Number of entries" field
   // (and remember its position).  We'll fill this field in later:
-  unsigned numEntriesPosition = ftell(fOutFid);
+  int64_t numEntriesPosition = TellFile64(fOutFid);
   size += addWord(0); // dummy for "Number of entries"
   unsigned numEdits = 0;
   unsigned totalDurationOfEdits = 0; // in movie time units
@@ -1525,7 +1605,7 @@ addAtom(gmin);
 addAtomEnd;
 
 unsigned QuickTimeFileSink::addAtom_hdlr2() {
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
   unsigned size = addAtomHeader("hdlr");
   size += addWord(0x00000000); // Version + Flags
   size += add4ByteString("dhlr"); // Component type
@@ -1557,7 +1637,7 @@ addAtom(stbl);
   }
   size += addAtom_stsc();
   size += addAtom_stsz();
-  size += addAtom_stco();
+  size += addAtom_co64();
 addAtomEnd;
 
 addAtom(stsd);
@@ -1569,7 +1649,7 @@ addAtom(stsd);
 addAtomEnd;
 
 unsigned QuickTimeFileSink::addAtom_genericMedia() {
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
 
   // Our source is assumed to be a "QuickTimeGenericRTPSource"
   // Use its "sdAtom" state for our contents:
@@ -1582,7 +1662,7 @@ unsigned QuickTimeFileSink::addAtom_genericMedia() {
 addAtomEnd;
 
 unsigned QuickTimeFileSink::addAtom_soundMediaGeneral() {
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
   unsigned size = addAtomHeader(fCurrentIOState->fQTAudioDataType);
 
 // General sample description fields:
@@ -1606,7 +1686,7 @@ addAtomEnd;
 unsigned QuickTimeFileSink::addAtom_Qclp() {
   // The beginning of this atom looks just like a general Sound Media atom,
   // except with a version field of 1:
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
   fCurrentIOState->fQTAudioDataType = "Qclp";
   fCurrentIOState->fQTSoundSampleVersion = 1;
   unsigned size = addAtom_soundMediaGeneral();
@@ -1659,16 +1739,20 @@ addAtom(Hclp);
 addAtomEnd;
 
 unsigned QuickTimeFileSink::addAtom_mp4a() {
+  unsigned size = 0;
   // The beginning of this atom looks just like a general Sound Media atom,
   // except with a version field of 1:
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
   fCurrentIOState->fQTAudioDataType = "mp4a";
-  fCurrentIOState->fQTSoundSampleVersion = 1;
-  unsigned size = addAtom_soundMediaGeneral();
 
   if (fGenerateMP4Format) {
+    fCurrentIOState->fQTSoundSampleVersion = 0;
+    size = addAtom_soundMediaGeneral();
     size += addAtom_esds();
   } else {
+    fCurrentIOState->fQTSoundSampleVersion = 1;
+    size = addAtom_soundMediaGeneral();
+
     // Next, add the four fields that are particular to version 1:
     // (Later, parameterize these #####)
     size += addWord(fCurrentIOState->fQTTimeUnitsPerSample);
@@ -1710,7 +1794,6 @@ addAtom(esds);
   unsigned configSize;
   unsigned char* config
     = parseGeneralConfigStr(subsession.fmtp_config(), configSize);
-  if (configSize > 0) --configSize; // remove trailing '\0';
   size += addByte(configSize);
   for (unsigned i = 0; i < configSize; ++i) {
     size += addByte(config[i]);
@@ -1720,7 +1803,7 @@ addAtom(esds);
   if (strcmp(subsession.mediumName(), "audio") == 0) {
     // MPEG-4 audio
     size += addWord(0x06808080); // ???
-    size += addByte(0x01); // ???
+    size += addHalfWord(0x0102); // ???
   } else {
     // MPEG-4 video
     size += addHalfWord(0x0601); // ???
@@ -1847,7 +1930,7 @@ addAtom(mp4v);
 addAtomEnd;
 
 unsigned QuickTimeFileSink::addAtom_rtp() {
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
   unsigned size = addAtomHeader("rtp ");
 
   size += addWord(0x00000000); // Reserved (1st 4 bytes)
@@ -1867,7 +1950,7 @@ addAtom(stts); // Time-to-Sample
 
   // First, add a dummy "Number of entries" field
   // (and remember its position).  We'll fill this field in later:
-  unsigned numEntriesPosition = ftell(fOutFid);
+  int64_t numEntriesPosition = TellFile64(fOutFid);
   size += addWord(0); // dummy for "Number of entries"
 
   // Then, run through the chunk descriptors, and enter the entries
@@ -1909,32 +1992,41 @@ addAtom(stss); // Sync-Sample
 
   // First, add a dummy "Number of entries" field
   // (and remember its position).  We'll fill this field in later:
-  unsigned numEntriesPosition = ftell(fOutFid);
+  int64_t numEntriesPosition = TellFile64(fOutFid);
   size += addWord(0); // dummy for "Number of entries"
 
-  // Then, run through the chunk descriptors, counting up the total nuber of samples:
   unsigned numEntries = 0, numSamplesSoFar = 0;
-  unsigned const samplesPerFrame = fCurrentIOState->fQTSamplesPerFrame;
-  ChunkDescriptor* chunk = fCurrentIOState->fHeadChunk;
-  while (chunk != NULL) {
-    unsigned const numSamples = chunk->fNumFrames*samplesPerFrame;
-    numSamplesSoFar += numSamples;
-    chunk = chunk->fNextChunk;
-  }
-
-  // Then, write out the sample numbers that we deem correspond to 'sync samples':
-  unsigned i;
-  for (i = 0; i < numSamplesSoFar; i += 12) {
-    // For an explanation of the constant "12", see http://lists.live555.com/pipermail/live-devel/2009-July/010969.html
-    // (Perhaps we should really try to keep track of which 'samples' ('frames' for video) really are 'key frames'?)
-    size += addWord(i+1);
-    ++numEntries;
-  }
-
-  // Then, write out the last entry (if we haven't already done so):
-  if (i != (numSamplesSoFar - 1)) {
-    size += addWord(numSamplesSoFar);
-    ++numEntries;
+  if (fCurrentIOState->fHeadSyncFrame != NULL) {
+    SyncFrame* currentSyncFrame = fCurrentIOState->fHeadSyncFrame;
+    while(currentSyncFrame != NULL) {
+      ++numEntries;
+      size += addWord(currentSyncFrame->sfFrameNum);
+      currentSyncFrame = currentSyncFrame->nextSyncFrame;
+    }
+  } else {
+    // Then, run through the chunk descriptors, counting up the total nuber of samples:
+    unsigned const samplesPerFrame = fCurrentIOState->fQTSamplesPerFrame;
+    ChunkDescriptor* chunk = fCurrentIOState->fHeadChunk;
+    while (chunk != NULL) {
+      unsigned const numSamples = chunk->fNumFrames*samplesPerFrame;
+      numSamplesSoFar += numSamples;
+      chunk = chunk->fNextChunk;
+    }
+  
+    // Then, write out the sample numbers that we deem correspond to 'sync samples':
+    unsigned i;
+    for (i = 0; i < numSamplesSoFar; i += 12) {
+      // For an explanation of the constant "12", see http://lists.live555.com/pipermail/live-devel/2009-July/010969.html
+      // (Perhaps we should really try to keep track of which 'samples' ('frames' for video) really are 'key frames'?)
+      size += addWord(i+1);
+      ++numEntries;
+    }
+  
+    // Then, write out the last entry (if we haven't already done so):
+    if (i != (numSamplesSoFar - 1)) {
+      size += addWord(numSamplesSoFar);
+      ++numEntries;
+    }
   }
 
   // Now go back and fill in the "Number of entries" field:
@@ -1946,7 +2038,7 @@ addAtom(stsc); // Sample-to-Chunk
 
   // First, add a dummy "Number of entries" field
   // (and remember its position).  We'll fill this field in later:
-  unsigned numEntriesPosition = ftell(fOutFid);
+  int64_t numEntriesPosition = TellFile64(fOutFid);
   size += addWord(0); // dummy for "Number of entries"
 
   // Then, run through the chunk descriptors, and enter the entries
@@ -2037,14 +2129,14 @@ addAtom(stsz); // Sample Size
   }
 addAtomEnd;
 
-addAtom(stco); // Chunk Offset
+addAtom(co64); // Chunk Offset
   size += addWord(0x00000000); // Version+flags
   size += addWord(fCurrentIOState->fNumChunks); // Number of entries
 
   // Run through the chunk descriptors, entering the file offsets:
   ChunkDescriptor* chunk = fCurrentIOState->fHeadChunk;
   while (chunk != NULL) {
-    size += addWord(chunk->fOffsetInFile);
+    size += addWord64(chunk->fOffsetInFile);
 
     chunk = chunk->fNextChunk;
   }
@@ -2068,7 +2160,7 @@ addAtom(hnti);
 addAtomEnd;
 
 unsigned QuickTimeFileSink::addAtom_sdp() {
-  unsigned initFilePosn = ftell(fOutFid);
+  int64_t initFilePosn = TellFile64(fOutFid);
   unsigned size = addAtomHeader("sdp ");
 
   // Add this subsession's SDP lines:
@@ -2195,7 +2287,7 @@ addAtomEnd;
 addAtom(payt);
   MediaSubsession& ourSubsession = fCurrentIOState->fOurSubsession;
   RTPSource* rtpSource = ourSubsession.rtpSource();
-  size += addByte(rtpSource->rtpPayloadFormat());
+  size += addWord(rtpSource->rtpPayloadFormat());
 
   // Also, add a 'rtpmap' string: <mime-subtype>/<rtp-frequency>
   unsigned rtpmapStringLength = strlen(ourSubsession.codecName()) + 20;
@@ -2208,6 +2300,6 @@ addAtomEnd;
 
 // A dummy atom (with name "????"):
 unsigned QuickTimeFileSink::addAtom_dummy() {
-    unsigned initFilePosn = ftell(fOutFid);
+    int64_t initFilePosn = TellFile64(fOutFid);
     unsigned size = addAtomHeader("????");
 addAtomEnd;
diff --git a/liveMedia/RTCP.cpp b/liveMedia/RTCP.cpp
index 356b16e..ea2d74a 100644
--- a/liveMedia/RTCP.cpp
+++ b/liveMedia/RTCP.cpp
@@ -300,7 +300,7 @@ void RTCPInstance::addStreamSocket(int sockNum,
   fRTCPInterface.stopNetworkReading();
 
   // Add the RTCP-over-TCP interface:
-  fRTCPInterface.setStreamSocket(sockNum, streamChannelId);
+  fRTCPInterface.addStreamSocket(sockNum, streamChannelId);
 
   // Turn on background reading for this socket (in case it's not on already):
   TaskScheduler::BackgroundHandlerProc* handler
@@ -894,14 +894,11 @@ void RTCPInstance::onExpire1() {
 
 SDESItem::SDESItem(unsigned char tag, unsigned char const* value) {
   unsigned length = strlen((char const*)value);
-  if (length > 511) length = 511;
+  if (length > 0xFF) length = 0xFF; // maximum data length for a SDES item
 
   fData[0] = tag;
   fData[1] = (unsigned char)length;
   memmove(&fData[2], value, length);
-
-  // Pad the trailing bytes to a 4-byte boundary:
-  while ((length)%4 > 0) fData[2 + length++] = '\0';
 }
 
 unsigned SDESItem::totalSize() const {
diff --git a/liveMedia/RTPInterface.cpp b/liveMedia/RTPInterface.cpp
index 18e1f18..d49d544 100644
--- a/liveMedia/RTPInterface.cpp
+++ b/liveMedia/RTPInterface.cpp
@@ -56,6 +56,11 @@ public:
   RTPInterface* lookupRTPInterface(unsigned char streamChannelId);
   void deregisterRTPInterface(unsigned char streamChannelId);
 
+  void setServerRequestAlternativeByteHandler(ServerRequestAlternativeByteHandler* handler, void* clientData) {
+    fServerRequestAlternativeByteHandler = handler;
+    fServerRequestAlternativeByteHandlerClientData = clientData;
+  }
+
 private:
   static void tcpReadHandler(SocketDescriptor*, int mask);
 
@@ -63,12 +68,19 @@ private:
   UsageEnvironment& fEnv;
   int fOurSocketNum;
   HashTable* fSubChannelHashTable;
+  ServerRequestAlternativeByteHandler* fServerRequestAlternativeByteHandler;
+  void* fServerRequestAlternativeByteHandlerClientData;
 };
 
-static SocketDescriptor* lookupSocketDescriptor(UsageEnvironment& env,
-						int sockNum) {
+static SocketDescriptor* lookupSocketDescriptor(UsageEnvironment& env, int sockNum, Boolean createIfNotFound = True) {
   char const* key = (char const*)(long)sockNum;
-  return (SocketDescriptor*)(socketHashTable(env)->Lookup(key));
+  SocketDescriptor* socketDescriptor = (SocketDescriptor*)(socketHashTable(env)->Lookup(key));
+  if (socketDescriptor == NULL && createIfNotFound) {
+    socketDescriptor = new SocketDescriptor(env, sockNum);
+    socketHashTable(env)->Add((char const*)(long)(sockNum), socketDescriptor);
+  }
+
+  return socketDescriptor;
 }
 
 static void removeSocketDescription(UsageEnvironment& env, int sockNum) {
@@ -106,8 +118,6 @@ RTPInterface::~RTPInterface() {
   delete fTCPStreams;
 }
 
-Boolean RTPOverTCP_OK = True; // HACK: For detecting TCP socket failure externally #####
-
 void RTPInterface::setStreamSocket(int sockNum,
 				   unsigned char streamChannelId) {
   fGS->removeAllDestinations();
@@ -117,7 +127,6 @@ void RTPInterface::setStreamSocket(int sockNum,
 void RTPInterface::addStreamSocket(int sockNum,
 				   unsigned char streamChannelId) {
   if (sockNum < 0) return;
-  else RTPOverTCP_OK = True; //##### HACK
 
   for (tcpStreamRecord* streams = fTCPStreams; streams != NULL;
        streams = streams->fNext) {
@@ -131,7 +140,7 @@ void RTPInterface::addStreamSocket(int sockNum,
 }
 
 static void deregisterSocket(UsageEnvironment& env, int sockNum, unsigned char streamChannelId) {
-  SocketDescriptor* socketDescriptor = lookupSocketDescriptor(env, sockNum);
+  SocketDescriptor* socketDescriptor = lookupSocketDescriptor(env, sockNum, False);
   if (socketDescriptor != NULL) {
     socketDescriptor->deregisterRTPInterface(streamChannelId);
         // Note: This may delete "socketDescriptor",
@@ -157,6 +166,17 @@ void RTPInterface::removeStreamSocket(int sockNum,
   }
 }
 
+void RTPInterface::setServerRequestAlternativeByteHandler(ServerRequestAlternativeByteHandler* handler, void* clientData) {
+  for (tcpStreamRecord* streams = fTCPStreams; streams != NULL;
+       streams = streams->fNext) {
+    // Get (or create, if necessary) a socket descriptor for "streams->fStreamSocketNum":
+    SocketDescriptor* socketDescriptor = lookupSocketDescriptor(envir(), streams->fStreamSocketNum);
+
+    socketDescriptor->setServerRequestAlternativeByteHandler(handler, clientData);
+  }
+}
+
+
 void RTPInterface::sendPacket(unsigned char* packet, unsigned packetSize) {
   // Normal case: Send as a UDP packet:
   fGS->output(envir(), fGS->ttl(), packet, packetSize);
@@ -180,14 +200,7 @@ void RTPInterface
   for (tcpStreamRecord* streams = fTCPStreams; streams != NULL;
        streams = streams->fNext) {
     // Get a socket descriptor for "streams->fStreamSocketNum":
-    SocketDescriptor* socketDescriptor
-      = lookupSocketDescriptor(envir(), streams->fStreamSocketNum);
-    if (socketDescriptor == NULL) {
-      socketDescriptor
-	= new SocketDescriptor(envir(), streams->fStreamSocketNum);
-      socketHashTable(envir())->Add((char const*)(long)(streams->fStreamSocketNum),
-				    socketDescriptor);
-    }
+    SocketDescriptor* socketDescriptor = lookupSocketDescriptor(envir(), streams->fStreamSocketNum);
 
     // Tell it about our subChannel:
     socketDescriptor->registerRTPInterface(streams->fStreamChannelId, this);
@@ -219,7 +232,6 @@ Boolean RTPInterface::handleRead(unsigned char* buffer,
     if (curBytesRead <= 0) {
       bytesRead = 0;
       readSuccess = False;
-      RTPOverTCP_OK = False; // HACK #####
     } else {
       readSuccess = True;
     }
@@ -274,15 +286,15 @@ void sendRTPOverTCP(unsigned char* packet, unsigned packetSize,
     return;
   } while (0);
 
-  RTPOverTCP_OK = False; // HACK #####
 #ifdef DEBUG
   fprintf(stderr, "sendRTPOverTCP: failed!\n"); fflush(stderr);
 #endif
 }
 
 SocketDescriptor::SocketDescriptor(UsageEnvironment& env, int socketNum)
-  : fEnv(env), fOurSocketNum(socketNum),
-    fSubChannelHashTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
+  :fEnv(env), fOurSocketNum(socketNum),
+    fSubChannelHashTable(HashTable::create(ONE_WORD_HASH_KEYS)),
+   fServerRequestAlternativeByteHandler(NULL), fServerRequestAlternativeByteHandlerClientData(NULL) {
 }
 
 SocketDescriptor::~SocketDescriptor() {
@@ -322,21 +334,17 @@ void SocketDescriptor
   }
 }
 
-void SocketDescriptor::tcpReadHandler(SocketDescriptor* socketDescriptor,
-				      int mask) {
+void SocketDescriptor::tcpReadHandler(SocketDescriptor* socketDescriptor, int mask) {
   do {
     UsageEnvironment& env = socketDescriptor->fEnv; // abbrev
     int socketNum = socketDescriptor->fOurSocketNum;
 
-    // Begin by reading and discarding any characters that aren't '$'.
-    // Any such characters are probably regular RTSP responses or
-    // commands from the server.  At present, we can't do anything with
-    // these, because we have taken complete control of reading this socket.
-    // (Later, fix) #####
+    // Begin by reading any characters that aren't '$'.  Any such characters are regular RTSP commands or responses,
+    // which need to be handled separately.
     unsigned char c;
     struct sockaddr_in fromAddress;
     struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0;
-    do {
+    while (1) {
       int result = readSocket(env, socketNum, &c, 1, fromAddress, &timeout);
       if (result != 1) { // error reading TCP socket
 	if (result < 0) {
@@ -344,14 +352,17 @@ void SocketDescriptor::tcpReadHandler(SocketDescriptor* socketDescriptor,
 	}
 	return;
       }
-    } while (c != '$');
+
+      if (c == '$') break;
+      if (socketDescriptor->fServerRequestAlternativeByteHandler != NULL) {
+	(*socketDescriptor->fServerRequestAlternativeByteHandler)(socketDescriptor->fServerRequestAlternativeByteHandlerClientData, c);
+      }
+    }
 
     // The next byte is the stream channel id:
     unsigned char streamChannelId;
-    if (readSocket(env, socketNum, &streamChannelId, 1, fromAddress)
-	!= 1) break;
-    RTPInterface* rtpInterface
-      = socketDescriptor->lookupRTPInterface(streamChannelId);
+    if (readSocket(env, socketNum, &streamChannelId, 1, fromAddress) != 1) break;
+    RTPInterface* rtpInterface = socketDescriptor->lookupRTPInterface(streamChannelId);
     if (rtpInterface == NULL) break; // we're not interested in this channel
 
     // The next two bytes are the RTP or RTCP packet size (in network order)
diff --git a/liveMedia/RTSPClient.cpp b/liveMedia/RTSPClient.cpp
index 99cc7b1..e7382fa 100644
--- a/liveMedia/RTSPClient.cpp
+++ b/liveMedia/RTSPClient.cpp
@@ -24,9 +24,6 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 #include "Locale.hh"
 #include <GroupsockHelper.hh>
 #include "our_md5.h"
-#ifdef SUPPORT_REAL_RTSP
-#include "../RealRTSP/include/RealRTSP.hh"
-#endif
 
 ////////// RTSPClient //////////
 
@@ -55,20 +52,15 @@ Boolean RTSPClient::lookupByName(UsageEnvironment& env,
   return True;
 }
 
-unsigned RTSPClient::fCSeq = 0;
-
 RTSPClient::RTSPClient(UsageEnvironment& env,
 		       int verbosityLevel, char const* applicationName,
 		       portNumBits tunnelOverHTTPPortNum)
   : Medium(env),
     fVerbosityLevel(verbosityLevel),
     fTunnelOverHTTPPortNum(tunnelOverHTTPPortNum),
-    fInputSocketNum(-1), fOutputSocketNum(-1), fServerAddress(0),
+    fInputSocketNum(-1), fOutputSocketNum(-1), fServerAddress(0), fCSeq(0),
     fBaseURL(NULL), fTCPStreamIdCount(0), fLastSessionId(NULL),
     fSessionTimeoutParameter(0),
-#ifdef SUPPORT_REAL_RTSP
-    fRealChallengeStr(NULL), fRealETagStr(NULL),
-#endif
     fServerIsKasenna(False), fKasennaContentType(NULL),
     fServerIsMicrosoft(False)
 {
@@ -136,10 +128,6 @@ void RTSPClient::reset() {
   fCurrentAuthenticator.reset();
 
   delete[] fKasennaContentType; fKasennaContentType = NULL;
-#ifdef SUPPORT_REAL_RTSP
-  delete[] fRealChallengeStr; fRealChallengeStr = NULL;
-  delete[] fRealETagStr; fRealETagStr = NULL;
-#endif
   delete[] fLastSessionId; fLastSessionId = NULL;
 }
 
@@ -196,9 +184,6 @@ char* RTSPClient::describeURL(char const* url, Authenticator* authenticator,
       "%s"
       "%s"
       "%s"
-#ifdef SUPPORT_REAL_RTSP
-      REAL_DESCRIBE_HEADERS
-#endif
       "\r\n";
     unsigned cmdSize = strlen(cmdFmt)
       + strlen(url)
@@ -227,9 +212,6 @@ char* RTSPClient::describeURL(char const* url, Authenticator* authenticator,
     // we can handle.
     Boolean wantRedirection = False;
     char* redirectionURL = NULL;
-#ifdef SUPPORT_REAL_RTSP
-    delete[] fRealETagStr; fRealETagStr = new char[fResponseBufferSize];
-#endif
     if (responseCode == 301 || responseCode == 302) {
       wantRedirection = True;
       redirectionURL = new char[fResponseBufferSize]; // ensures enough space
@@ -272,9 +254,6 @@ char* RTSPClient::describeURL(char const* url, Authenticator* authenticator,
       } else if (sscanf(lineStart, "Server: %s", serverType) == 1) {
 	if (strncmp(serverType, "Kasenna", 7) == 0) fServerIsKasenna = True;
 	if (strncmp(serverType, "WMServer", 8) == 0) fServerIsMicrosoft = True;
-#ifdef SUPPORT_REAL_RTSP
-      } else if (sscanf(lineStart, "ETag: %s", fRealETagStr) == 1) {
-#endif
       } else if (wantRedirection) {
 	if (sscanf(lineStart, "Location: %s", redirectionURL) == 1) {
 	  // Try again with this URL
@@ -545,9 +524,6 @@ char* RTSPClient::sendOptionsCmd(char const* url,
       "CSeq: %d\r\n"
       "%s"
       "%s"
-#ifdef SUPPORT_REAL_RTSP
-      REAL_OPTIONS_HEADERS
-#endif
       "\r\n";
     unsigned cmdSize = strlen(cmdFmt)
       + strlen(url)
@@ -585,10 +561,6 @@ char* RTSPClient::sendOptionsCmd(char const* url,
 
       if (_strncasecmp(lineStart, "Public: ", 8) == 0) {
 	delete[] result; result = strDup(&lineStart[8]);
-#ifdef SUPPORT_REAL_RTSP
-      } else if (_strncasecmp(lineStart, "RealChallenge1: ", 16) == 0) {
-	delete[] fRealChallengeStr; fRealChallengeStr = strDup(&lineStart[16]);
-#endif
       }
     }
   } while (0);
@@ -769,73 +741,6 @@ Boolean RTSPClient::setupMediaSubsession(MediaSubsession& subsession,
     }
 
     char* transportStr = NULL;
-#ifdef SUPPORT_REAL_RTSP
-    if (usingRealNetworksChallengeResponse()) {
-      // Use a special "Transport:" header, and also add a 'challenge response'.
-      char challenge2[64];
-      char checksum[34];
-      RealCalculateChallengeResponse(fRealChallengeStr, challenge2, checksum);
-
-      char const* etag = fRealETagStr == NULL ? "" : fRealETagStr;
-
-      char* transportHeader;
-      if (subsession.parentSession().isRealNetworksRDT) {
-	transportHeader = strDup("Transport: x-pn-tng/tcp;mode=play,rtp/avp/unicast;mode=play\r\n");
-      } else {
-	// Use a regular "Transport:" header:
-	char const* transportHeaderFmt
-	  = "Transport: RTP/AVP%s%s=%d-%d\r\n";
-	char const* transportTypeStr;
-	char const* portTypeStr;
-	unsigned short rtpNumber, rtcpNumber;
-	if (streamUsingTCP) { // streaming over the RTSP connection
-	  transportTypeStr = "/TCP;unicast";
-	  portTypeStr = ";interleaved";
-	  rtpNumber = fTCPStreamIdCount++;
-	  rtcpNumber = fTCPStreamIdCount++;
-	} else { // normal RTP streaming
-	  unsigned connectionAddress = subsession.connectionEndpointAddress();
-	  Boolean requestMulticastStreaming = IsMulticastAddress(connectionAddress)
-	    || (connectionAddress == 0 && forceMulticastOnUnspecified);
-	  transportTypeStr = requestMulticastStreaming ? ";multicast" : ";unicast";
-	  portTypeStr = ";client_port";
-	  rtpNumber = subsession.clientPortNum();
-	  if (rtpNumber == 0) {
-	    envir().setResultMsg("Client port number unknown\n");
-	    break;
-	  }
-	  rtcpNumber = rtpNumber + 1;
-	}
-
-	unsigned transportHeaderSize = strlen(transportHeaderFmt)
-	  + strlen(transportTypeStr) + strlen(portTypeStr) + 2*5 /* max port len */;
-	transportHeader = new char[transportHeaderSize];
-	sprintf(transportHeader, transportHeaderFmt,
-		transportTypeStr, portTypeStr, rtpNumber, rtcpNumber);
-      }
-      char const* transportFmt =
-	"%s"
-	"RealChallenge2: %s, sd=%s\r\n"
-	"If-Match: %s\r\n";
-      unsigned transportSize = strlen(transportFmt)
-	+ strlen(transportHeader)
-	+ sizeof challenge2 + sizeof checksum
-	+ strlen(etag);
-      transportStr = new char[transportSize];
-      sprintf(transportStr, transportFmt,
-	      transportHeader,
-	      challenge2, checksum,
-	      etag);
-      delete[] transportHeader;
-
-      if (subsession.parentSession().isRealNetworksRDT) {
-	// Also, tell the RDT source to use the RTSP TCP socket:
-	RealRDTSource* rdtSource
-	  = (RealRDTSource*)(subsession.readSource());
-	rdtSource->setInputSocket(fInputSocketNum);
-      }
-    }
-#endif
 
     char const *prefix, *separator, *suffix;
     constructSubsessionURL(subsession, prefix, separator, suffix);
@@ -1048,14 +953,6 @@ static char const* NoSessionErr = "No RTSP session is currently in progress\n";
 
 Boolean RTSPClient::playMediaSession(MediaSession& session,
 				     double start, double end, float scale) {
-#ifdef SUPPORT_REAL_RTSP
-  if (session.isRealNetworksRDT) {
-    // This is a RealNetworks stream; set the "Subscribe" parameter before proceeding:
-    char* streamRuleString = RealGetSubscribeRuleString(&session);
-    setMediaSessionParameter(session, "Subscribe", streamRuleString);
-    delete[] streamRuleString;
-  }
-#endif
   char* cmd = NULL;
   do {
     // First, make sure that we have a RTSP session in progress
diff --git a/liveMedia/RTSPServer.cpp b/liveMedia/RTSPServer.cpp
index df613c8..5cb2cc2 100644
--- a/liveMedia/RTSPServer.cpp
+++ b/liveMedia/RTSPServer.cpp
@@ -299,43 +299,58 @@ void RTSPServer::RTSPClientSession::resetRequestBuffer() {
   fLastCRLF = &fRequestBuffer[-3]; // hack
 }
 
-void RTSPServer::RTSPClientSession
-::incomingRequestHandler(void* instance, int /*mask*/) {
+void RTSPServer::RTSPClientSession::incomingRequestHandler(void* instance, int /*mask*/) {
   RTSPClientSession* session = (RTSPClientSession*)instance;
   session->incomingRequestHandler1();
 }
 
 void RTSPServer::RTSPClientSession::incomingRequestHandler1() {
-  noteLiveness();
-
   struct sockaddr_in dummy; // 'from' address, meaningless in this case
-  Boolean endOfMsg = False;
-  unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
 
-  int bytesRead = readSocket(envir(), fClientSocket,
-			     ptr, fRequestBufferBytesLeft, dummy);
-  if (bytesRead <= 0 || (unsigned)bytesRead >= fRequestBufferBytesLeft) {
+  int bytesRead = readSocket(envir(), fClientSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy);
+  handleRequestBytes(bytesRead);
+}
+
+void RTSPServer::RTSPClientSession::handleAlternativeRequestByte(void* instance, u_int8_t requestByte) {
+  RTSPClientSession* session = (RTSPClientSession*)instance;
+  session->handleAlternativeRequestByte1(requestByte);
+}
+
+void RTSPServer::RTSPClientSession::handleAlternativeRequestByte1(u_int8_t requestByte) {
+  // Add this character to our buffer; then try to handle the data that we have buffered so far:
+  if (fRequestBufferBytesLeft == 0) return;
+  fRequestBuffer[fRequestBytesAlreadySeen] = requestByte;
+  handleRequestBytes(1);
+}
+
+void RTSPServer::RTSPClientSession::handleRequestBytes(int newBytesRead) {
+  noteLiveness();
+
+  if (newBytesRead <= 0 || (unsigned)newBytesRead >= fRequestBufferBytesLeft) {
     // Either the client socket has died, or the request was too big for us.
     // Terminate this connection:
 #ifdef DEBUG
-    fprintf(stderr, "RTSPClientSession[%p]::incomingRequestHandler1() read %d bytes (of %d); terminating connection!\n", this, bytesRead, fRequestBufferBytesLeft);
+    fprintf(stderr, "RTSPClientSession[%p]::handleRequestBytes() read %d new bytes (of %d); terminating connection!\n", this, newBytesRead, fRequestBufferBytesLeft);
 #endif
     delete this;
     return;
   }
+
+  Boolean endOfMsg = False;
+  unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
 #ifdef DEBUG
-  ptr[bytesRead] = '\0';
-  fprintf(stderr, "RTSPClientSession[%p]::incomingRequestHandler1() read %d bytes:%s\n", this, bytesRead, ptr);
+  ptr[newBytesRead] = '\0';
+  fprintf(stderr, "RTSPClientSession[%p]::handleRequestBytes() read %d new bytes:%s\n", this, newBytesRead, ptr);
 #endif
 
   // Look for the end of the message: <CR><LF><CR><LF>
   unsigned char *tmpPtr = ptr;
   if (fRequestBytesAlreadySeen > 0) --tmpPtr;
       // in case the last read ended with a <CR>
-  while (tmpPtr < &ptr[bytesRead-1]) {
+  while (tmpPtr < &ptr[newBytesRead-1]) {
     if (*tmpPtr == '\r' && *(tmpPtr+1) == '\n') {
       if (tmpPtr - fLastCRLF == 2) { // This is it:
-	endOfMsg = 1;
+	endOfMsg = True;
 	break;
       }
       fLastCRLF = tmpPtr;
@@ -343,8 +358,8 @@ void RTSPServer::RTSPClientSession::incomingRequestHandler1() {
     ++tmpPtr;
   }
 
-  fRequestBufferBytesLeft -= bytesRead;
-  fRequestBytesAlreadySeen += bytesRead;
+  fRequestBufferBytesLeft -= newBytesRead;
+  fRequestBytesAlreadySeen += newBytesRead;
 
   if (!endOfMsg) return; // subsequent reads will be needed to complete the request
 
@@ -433,8 +448,7 @@ static char const* dateHeader() {
 }
 
 static char const* allowedCommandNames
-//  = "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER";
-= "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, SET_PARAMETER"; // TEMP HACK to stop VLC from using "GET_PARAMETER" as a client 'keep-alive' indicator; we don't need this, and it currently causes problems for RTP-over-TCP streams.
+= "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER";
 
 void RTSPServer::RTSPClientSession::handleCmd_bad(char const* /*cseq*/) {
   // Don't do anything with "cseq", because it might be nonsense
@@ -990,10 +1004,9 @@ void RTSPServer::RTSPClientSession
       unsigned rtpTimestamp = 0;
       fStreamStates[i].subsession->startStream(fOurSessionId,
 					       fStreamStates[i].streamToken,
-					       (TaskFunc*)noteClientLiveness,
-					       this,
-					       rtpSeqNum,
-					       rtpTimestamp);
+					       (TaskFunc*)noteClientLiveness, this,
+					       rtpSeqNum, rtpTimestamp,
+					       handleAlternativeRequestByte, this);
       const char *urlSuffix = fStreamStates[i].subsession->trackId();
       char* prevRTPInfo = rtpInfo;
       unsigned rtpInfoSize = rtpInfoFmtSize
diff --git a/liveMedia/SIPClient.cpp b/liveMedia/SIPClient.cpp
index a7bf67e..0e4eee5 100644
--- a/liveMedia/SIPClient.cpp
+++ b/liveMedia/SIPClient.cpp
@@ -168,7 +168,6 @@ static char* getLine(char* startOfLine) {
 
 char* SIPClient::invite(char const* url, Authenticator* authenticator) {
   // First, check whether "url" contains a username:password to be used:
-  fInviteStatusCode = 0;
   char* username; char* password;
   if (authenticator == NULL
       && parseSIPURLUsernamePassword(url, username, password)) {
@@ -314,7 +313,6 @@ char* SIPClient::invite1(Authenticator* authenticator) {
     }
   } while (0);
 
-  fInviteStatusCode = 2;
   return NULL;
 }
 
@@ -731,7 +729,6 @@ Boolean SIPClient::processURL(char const* url) {
     return True;
   } while (0);
 
-  fInviteStatusCode = 1;
   return False;
 }
 
diff --git a/liveMedia/include/DigestAuthentication.hh b/liveMedia/include/DigestAuthentication.hh
index e999ea1..0e22bcb 100644
--- a/liveMedia/include/DigestAuthentication.hh
+++ b/liveMedia/include/DigestAuthentication.hh
@@ -32,6 +32,7 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 class Authenticator {
 public:
   Authenticator();
+  Authenticator(char const* username, char const* password);
   Authenticator(const Authenticator& orig);
   Authenticator& operator=(const Authenticator& rightSide);
   virtual ~Authenticator();
diff --git a/liveMedia/include/MPEG2TransportFileServerMediaSubsession.hh b/liveMedia/include/MPEG2TransportFileServerMediaSubsession.hh
index 37a58aa..034ded7 100644
--- a/liveMedia/include/MPEG2TransportFileServerMediaSubsession.hh
+++ b/liveMedia/include/MPEG2TransportFileServerMediaSubsession.hh
@@ -55,7 +55,9 @@ private: // redefined virtual functions
                            TaskFunc* rtcpRRHandler,
                            void* rtcpRRHandlerClientData,
                            unsigned short& rtpSeqNum,
-                           unsigned& rtpTimestamp);
+                           unsigned& rtpTimestamp,
+			   ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+                           void* serverRequestAlternativeByteHandlerClientData);
   virtual void pauseStream(unsigned clientSessionId, void* streamToken);
   virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT);
   virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
diff --git a/liveMedia/include/MediaSession.hh b/liveMedia/include/MediaSession.hh
index 6b7758b..5325713 100644
--- a/liveMedia/include/MediaSession.hh
+++ b/liveMedia/include/MediaSession.hh
@@ -56,16 +56,6 @@ public:
       // Initiates the first subsession with the specified MIME type
       // Returns the resulting subsession, or 'multi source' (not both)
 
-#ifdef SUPPORT_REAL_RTSP
-  // Attributes specific to RealNetworks streams:
-  Boolean isRealNetworksRDT;
-  unsigned fRealFlags;
-  unsigned char* fRealTitle; unsigned fRealTitleSize;
-  unsigned char* fRealAuthor; unsigned fRealAuthorSize;
-  unsigned char* fRealCopyright; unsigned fRealCopyrightSize;
-  unsigned char* fRealAbstract; unsigned fRealAbstractSize;
-#endif
-
 protected: // redefined virtual functions
   virtual Boolean isMediaSession() const;
 
@@ -229,16 +219,6 @@ public:
   // Also, for this function to work properly, the RTP stream's presentation times must (eventually) be
   // synchronized via RTCP.
 
-#ifdef SUPPORT_REAL_RTSP
-  // Attributes specific to RealNetworks streams:
-  unsigned fRealMaxBitRate, fRealAvgBitRate, fRealMaxPacketSize, fRealAvgPacketSize, fRealPreroll;
-  char* fRealStreamName; char* fRealMIMEType;
-  unsigned char* fRealOpaqueData; unsigned fRealOpaqueDataSize;
-  // A pointer into "fRealOpaqueData":
-  unsigned char* fRealTypeSpecificData; unsigned fRealTypeSpecificDataSize;
-  unsigned fRealRuleNumber;
-#endif
-
 protected:
   friend class MediaSession;
   friend class MediaSubsessionIterator;
diff --git a/liveMedia/include/OnDemandServerMediaSubsession.hh b/liveMedia/include/OnDemandServerMediaSubsession.hh
index 21b0cde..08b73b7 100644
--- a/liveMedia/include/OnDemandServerMediaSubsession.hh
+++ b/liveMedia/include/OnDemandServerMediaSubsession.hh
@@ -54,7 +54,9 @@ protected: // redefined virtual functions
 			   TaskFunc* rtcpRRHandler,
 			   void* rtcpRRHandlerClientData,
 			   unsigned short& rtpSeqNum,
-                           unsigned& rtpTimestamp);
+                           unsigned& rtpTimestamp,
+			   ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+                           void* serverRequestAlternativeByteHandlerClientData);
   virtual void pauseStream(unsigned clientSessionId, void* streamToken);
   virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT);
   virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
diff --git a/liveMedia/include/PassiveServerMediaSubsession.hh b/liveMedia/include/PassiveServerMediaSubsession.hh
index 56f84f2..57770f8 100644
--- a/liveMedia/include/PassiveServerMediaSubsession.hh
+++ b/liveMedia/include/PassiveServerMediaSubsession.hh
@@ -62,7 +62,9 @@ protected: // redefined virtual functions
 			   TaskFunc* rtcpRRHandler,
 			   void* rtcpRRHandlerClientData,
                            unsigned short& rtpSeqNum,
-                           unsigned& rtpTimestamp);
+                           unsigned& rtpTimestamp,
+			   ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+                           void* serverRequestAlternativeByteHandlerClientData);
 
 protected:
   char* fSDPLines;
diff --git a/liveMedia/include/QuickTimeFileSink.hh b/liveMedia/include/QuickTimeFileSink.hh
index 0592a69..7491171 100644
--- a/liveMedia/include/QuickTimeFileSink.hh
+++ b/liveMedia/include/QuickTimeFileSink.hh
@@ -85,6 +85,7 @@ private:
 private:
   ///// Definitions specific to the QuickTime file format:
 
+  unsigned addWord64(u_int64_t word);
   unsigned addWord(unsigned word);
   unsigned addHalfWord(unsigned short halfWord);
   unsigned addByte(unsigned char byte) {
@@ -96,8 +97,10 @@ private:
   unsigned addArbitraryString(char const* str,
 			      Boolean oneByteLength = True);
   unsigned addAtomHeader(char const* atomName);
+  unsigned addAtomHeader64(char const* atomName);
       // strlen(atomName) must be 4
-  void setWord(unsigned filePosn, unsigned size);
+  void setWord(int64_t filePosn, unsigned size);
+  void setWord64(int64_t filePosn, u_int64_t size);
 
   unsigned movieTimeScale() const {return fLargestRTPtimestampFrequency;}
 
@@ -151,7 +154,7 @@ private:
                       _atom(stss);
                       _atom(stsc);
                       _atom(stsz);
-                      _atom(stco);
+                      _atom(co64);
           _atom(udta);
               _atom(name);
               _atom(hnti);
@@ -176,8 +179,8 @@ private:
 private:
   unsigned short fMovieWidth, fMovieHeight;
   unsigned fMovieFPS;
-  unsigned fMDATposition;
-  unsigned fMVHD_durationPosn;
+  int64_t fMDATposition;
+  int64_t fMVHD_durationPosn;
   unsigned fMaxTrackDurationM; // in movie time units
   class SubsessionIOState* fCurrentIOState;
 };
diff --git a/liveMedia/include/RTPInterface.hh b/liveMedia/include/RTPInterface.hh
index 4bb990a..ddbd030 100644
--- a/liveMedia/include/RTPInterface.hh
+++ b/liveMedia/include/RTPInterface.hh
@@ -35,6 +35,11 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 typedef void AuxHandlerFunc(void* clientData, unsigned char* packet,
 			    unsigned packetSize);
 
+typedef void ServerRequestAlternativeByteHandler(void* instance, u_int8_t requestByte);
+// A hack that allows a handler for RTP/RTCP packets received over TCP to process RTSP commands that may also appear within
+// the same TCP connection.  A RTSP server implementation would supply a function like this - as a parameter to
+// "ServerMediaSubsession::startStream()".
+
 class tcpStreamRecord {
 public:
   tcpStreamRecord(int streamSocketNum, unsigned char streamChannelId,
@@ -57,6 +62,7 @@ public:
   void setStreamSocket(int sockNum, unsigned char streamChannelId);
   void addStreamSocket(int sockNum, unsigned char streamChannelId);
   void removeStreamSocket(int sockNum, unsigned char streamChannelId);
+  void setServerRequestAlternativeByteHandler(ServerRequestAlternativeByteHandler* handler, void* clientData);
 
   void sendPacket(unsigned char* packet, unsigned packetSize);
   void startNetworkReading(TaskScheduler::BackgroundHandlerProc*
diff --git a/liveMedia/include/RTPSink.hh b/liveMedia/include/RTPSink.hh
index 425be8a..b8eeff3 100644
--- a/liveMedia/include/RTPSink.hh
+++ b/liveMedia/include/RTPSink.hh
@@ -80,6 +80,9 @@ public:
   void removeStreamSocket(int sockNum, unsigned char streamChannelId) {
     fRTPInterface.removeStreamSocket(sockNum, streamChannelId);
   }
+  void setServerRequestAlternativeByteHandler(ServerRequestAlternativeByteHandler* handler, void* clientData) {
+    fRTPInterface.setServerRequestAlternativeByteHandler(handler, clientData);
+  }
     // hacks to allow sending RTP over TCP (RFC 2236, section 10.12)
 
   void getTotalBitrate(unsigned& outNumBytes, double& outElapsedTime);
diff --git a/liveMedia/include/RTSPClient.hh b/liveMedia/include/RTSPClient.hh
index 70f4755..8dacaf5 100644
--- a/liveMedia/include/RTSPClient.hh
+++ b/liveMedia/include/RTSPClient.hh
@@ -150,10 +150,6 @@ public:
 
   unsigned sessionTimeoutParameter() const { return fSessionTimeoutParameter; }
 
-#ifdef SUPPORT_REAL_RTSP
-  Boolean usingRealNetworksChallengeResponse() const { return fRealChallengeStr != NULL; }
-#endif
-
 protected:
   RTSPClient(UsageEnvironment& env, int verbosityLevel,
 	     char const* applicationName, portNumBits tunnelOverHTTPPortNum);
@@ -211,19 +207,12 @@ private:
       unsigned fUserAgentHeaderStrSize;
   int fInputSocketNum, fOutputSocketNum;
   unsigned fServerAddress;
-  static unsigned fCSeq; // sequence number, used in consecutive requests
-      // Note: it's static, to ensure that it differs if more than one
-      // connection is made to the same server, using the same URL.
-      // Some servers (e.g., DSS) may have problems with this otherwise.
+  unsigned fCSeq; // sequence number, used in consecutive requests
   char* fBaseURL;
   Authenticator fCurrentAuthenticator;
   unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
   char* fLastSessionId;
   unsigned fSessionTimeoutParameter; // optionally set in response "Session:" headers
-#ifdef SUPPORT_REAL_RTSP
-  char* fRealChallengeStr;
-  char* fRealETagStr;
-#endif
   unsigned fDescribeStatusCode;
   // 0: OK; 1: connection failed; 2: stream unavailable
   char* fResponseBuffer;
diff --git a/liveMedia/include/RTSPServer.hh b/liveMedia/include/RTSPServer.hh
index 4ba87bb..aba4a0c 100644
--- a/liveMedia/include/RTSPServer.hh
+++ b/liveMedia/include/RTSPServer.hh
@@ -151,6 +151,9 @@ protected:
     Boolean isMulticast() const { return fIsMulticast; }
     static void incomingRequestHandler(void*, int /*mask*/);
     void incomingRequestHandler1();
+    static void handleAlternativeRequestByte(void*, u_int8_t requestByte);
+    void handleAlternativeRequestByte1(u_int8_t requestByte);
+    void handleRequestBytes(int newBytesRead);
     void noteLiveness();
     static void noteClientLiveness(RTSPClientSession* clientSession);
     static void livenessTimeoutTask(RTSPClientSession* clientSession);
diff --git a/liveMedia/include/SIPClient.hh b/liveMedia/include/SIPClient.hh
index 77c3d21..d1daea1 100644
--- a/liveMedia/include/SIPClient.hh
+++ b/liveMedia/include/SIPClient.hh
@@ -68,8 +68,6 @@ public:
 					     char*& username,
 					     char*& password);
 
-  unsigned inviteStatus() const { return fInviteStatusCode; }
-
 protected:
   virtual ~SIPClient();
 
@@ -141,8 +139,6 @@ private:
   Authenticator* fWorkingAuthenticator;
   inviteClientState fInviteClientState;
   char fEventLoopStopFlag;
-  unsigned fInviteStatusCode;
-  // 0: OK; 1: connection failed; 2: stream unavailable
 };
 
 #endif
diff --git a/liveMedia/include/ServerMediaSession.hh b/liveMedia/include/ServerMediaSession.hh
index 373422f..ff59f63 100644
--- a/liveMedia/include/ServerMediaSession.hh
+++ b/liveMedia/include/ServerMediaSession.hh
@@ -30,6 +30,9 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 #ifndef _GROUPEID_HH
 #include "GroupEId.hh"
 #endif
+#ifndef _RTP_INTERFACE_HH
+#include "RTPInterface.hh" // for ServerRequestAlternativeByteHandler
+#endif
 
 class ServerMediaSubsession; // forward
 
@@ -133,7 +136,9 @@ public:
 			   TaskFunc* rtcpRRHandler,
 			   void* rtcpRRHandlerClientData,
 			   unsigned short& rtpSeqNum,
-			   unsigned& rtpTimestamp) = 0;
+			   unsigned& rtpTimestamp,
+			   ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+			   void* serverRequestAlternativeByteHandlerClientData) = 0;
   virtual void pauseStream(unsigned clientSessionId, void* streamToken);
   virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT);
   virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
diff --git a/liveMedia/include/liveMedia_version.hh b/liveMedia/include/liveMedia_version.hh
index e10703f..4dc2f03 100644
--- a/liveMedia/include/liveMedia_version.hh
+++ b/liveMedia/include/liveMedia_version.hh
@@ -4,7 +4,7 @@
 #ifndef _LIVEMEDIA_VERSION_HH
 #define _LIVEMEDIA_VERSION_HH
 
-#define LIVEMEDIA_LIBRARY_VERSION_STRING	"2010.02.10"
-#define LIVEMEDIA_LIBRARY_VERSION_INT		1265760000
+#define LIVEMEDIA_LIBRARY_VERSION_STRING	"2010.04.09"
+#define LIVEMEDIA_LIBRARY_VERSION_INT		1270771200
 
 #endif
diff --git a/mediaServer/version.hh b/mediaServer/version.hh
index 118324a..6a65ff8 100644
--- a/mediaServer/version.hh
+++ b/mediaServer/version.hh
@@ -5,6 +5,6 @@
 #ifndef _MEDIA_SERVER_VERSION_HH
 #define _MEDIA_SERVER_VERSION_HH
 
-#define MEDIA_SERVER_VERSION_STRING "0.41"
+#define MEDIA_SERVER_VERSION_STRING "0.42"
 
 #endif
diff --git a/testProgs/openRTSP.cpp b/testProgs/openRTSP.cpp
index 39ca683..a313b12 100644
--- a/testProgs/openRTSP.cpp
+++ b/testProgs/openRTSP.cpp
@@ -45,8 +45,6 @@ char* getSDPDescriptionFromURL(Medium* client, char const* url,
     result = rtspClient->describeURL(url);
   }
 
-  extern unsigned statusCode;
-  statusCode = rtspClient->describeStatus();
   return result;
 }
 
diff --git a/testProgs/playCommon.cpp b/testProgs/playCommon.cpp
index d8e4b83..fbbfcb6 100644
--- a/testProgs/playCommon.cpp
+++ b/testProgs/playCommon.cpp
@@ -20,9 +20,6 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
 #include "playCommon.hh"
 #include "BasicUsageEnvironment.hh"
 #include "GroupsockHelper.hh"
-#ifdef SUPPORT_REAL_RTSP
-#include "../RealRTSP/include/RealRTSP.hh"
-#endif
 
 #if defined(__WIN32__) || defined(_WIN32)
 #define snprintf _snprintf
@@ -97,7 +94,6 @@ Boolean packetLossCompensate = False;
 Boolean syncStreams = False;
 Boolean generateHintTracks = False;
 unsigned qosMeasurementIntervalMS = 0; // 0 means: Don't output QOS data
-unsigned statusCode = 0;
 
 struct timeval startTime;
 
@@ -649,44 +645,6 @@ int main(int argc, char** argv) {
       }
 
       aviOut->startPlaying(sessionAfterPlaying, NULL);
-#ifdef SUPPORT_REAL_RTSP
-    } else if (session->isRealNetworksRDT) {
-      // For RealNetworks' sessions, we create a single output file,
-      // named "output.rm".
-      char outFileName[1000];
-      if (singleMedium == NULL) {
-	snprintf(outFileName, sizeof outFileName, "%soutput.rm", fileNamePrefix);
-      } else {
-	// output to 'stdout' as normal, even though we actually output all media
-	sprintf(outFileName, "stdout");
-      }
-      FileSink* fileSink = FileSink::createNew(*env, outFileName,
-					       fileSinkBufferSize, oneFilePerFrame);
-
-      // The output file needs to begin with a special 'RMFF' header,
-      // in order for it to be usable.  Write this header first:
-      unsigned headerSize;
-      unsigned char* headerData = RealGenerateRMFFHeader(session, headerSize);
-      struct timeval timeNow;
-      gettimeofday(&timeNow, NULL);
-      fileSink->addData(headerData, headerSize, timeNow);
-      delete[] headerData;
-
-      // Start playing the output file from the first subsession.
-      // (Hack: Because all subsessions' data is actually multiplexed on the
-      // single RTSP TCP connection, playing from one subsession is sufficient.)
-      iter.reset();
-      madeProgress = False;
-      while ((subsession = iter.next()) != NULL) {
-	if (subsession->readSource() == NULL) continue; // was not initiated
-
-	fileSink->startPlaying(*(subsession->readSource()),
-			       subsessionAfterPlaying, subsession);
-	madeProgress = True;
-	break; // play from one subsession only
-      }
-      if (!madeProgress) shutdown();
-#endif
     } else {
       // Create and start "FileSink"s for each subsession:
       madeProgress = False;
@@ -826,21 +784,12 @@ void startPlayingStreams() {
   Boolean timerIsBeingUsed = False;
   double secondsToDelay = duration;
   if (duration > 0) {
-    double const maxDelayTime
-      = (double)( ((unsigned)0x7FFFFFFF)/1000000.0 );
-    if (duration > maxDelayTime) {
-      *env << "Warning: specified end time " << duration
-		<< " exceeds maximum " << maxDelayTime
-		<< "; will not do a delayed shutdown\n";
-    } else {
-      timerIsBeingUsed = True;
-      double absScale = scale > 0 ? scale : -scale; // ASSERT: scale != 0
-      secondsToDelay = duration/absScale + durationSlop;
+    timerIsBeingUsed = True;
+    double absScale = scale > 0 ? scale : -scale; // ASSERT: scale != 0
+    secondsToDelay = duration/absScale + durationSlop;
 
-      int uSecsToDelay = (int)(secondsToDelay*1000000.0);
-      sessionTimerTask = env->taskScheduler().scheduleDelayedTask(
-         uSecsToDelay, (TaskFunc*)sessionTimerHandler, (void*)NULL);
-    }
+    int64_t uSecsToDelay = (int64_t)(secondsToDelay*1000000.0);
+    sessionTimerTask = env->taskScheduler().scheduleDelayedTask(uSecsToDelay, (TaskFunc*)sessionTimerHandler, (void*)NULL);
   }
 
   char const* actionString
@@ -942,15 +891,6 @@ public:
       totNumPacketsReceived(0), totNumPacketsExpected(0) {
     measurementEndTime = measurementStartTime = startTime;
 
-#ifdef SUPPORT_REAL_RTSP
-    if (session->isRealNetworksRDT) { // hack for RealMedia sessions (RDT, not RTP)
-      RealRDTSource* rdt = (RealRDTSource*)src;
-      kBytesTotal = rdt->totNumKBytesReceived();
-      totNumPacketsReceived = rdt->totNumPacketsReceived();
-      totNumPacketsExpected = totNumPacketsReceived; // because we use TCP
-      return;
-    }
-#endif
     RTPReceptionStatsDB::Iterator statsIter(src->receptionStatsDB());
     // Assume that there's only one SSRC source (usually the case):
     RTPReceptionStats* stats = statsIter.next(True);
@@ -1014,24 +954,6 @@ void qosMeasurementRecord
   double timeDiff = secsDiff + usecsDiff/1000000.0;
   measurementEndTime = timeNow;
 
-#ifdef SUPPORT_REAL_RTSP
-  if (session->isRealNetworksRDT) { // hack for RealMedia sessions (RDT, not RTP)
-    RealRDTSource* rdt = (RealRDTSource*)fSource;
-    double kBytesTotalNow = rdt->totNumKBytesReceived();
-    double kBytesDeltaNow = kBytesTotalNow - kBytesTotal;
-    kBytesTotal = kBytesTotalNow;
-
-    double kbpsNow = timeDiff == 0.0 ? 0.0 : 8*kBytesDeltaNow/timeDiff;
-    if (kbpsNow < 0.0) kbpsNow = 0.0; // in case of roundoff error
-    if (kbpsNow < kbits_per_second_min) kbits_per_second_min = kbpsNow;
-    if (kbpsNow > kbits_per_second_max) kbits_per_second_max = kbpsNow;
-
-    totNumPacketsReceived = rdt->totNumPacketsReceived();
-    totNumPacketsExpected = totNumPacketsReceived; // because we use TCP
-    packet_loss_fraction_min = packet_loss_fraction_max = 0.0; // ditto
-    return;
-  }
-#endif
   RTPReceptionStatsDB::Iterator statsIter(fSource->receptionStatsDB());
   // Assume that there's only one SSRC source (usually the case):
   RTPReceptionStats* stats = statsIter.next(True);
@@ -1074,9 +996,6 @@ void beginQOSMeasurement() {
   MediaSubsession* subsession;
   while ((subsession = iter.next()) != NULL) {
     RTPSource* src = subsession->rtpSource();
-#ifdef SUPPORT_REAL_RTSP
-    if (session->isRealNetworksRDT) src = (RTPSource*)(subsession->readSource()); // hack
-#endif
     if (src == NULL) continue;
 
     qosMeasurementRecord* qosRecord
@@ -1091,11 +1010,8 @@ void beginQOSMeasurement() {
 }
 
 void printQOSData(int exitCode) {
-  if (exitCode != 0 && statusCode == 0) statusCode = 2;
   *env << "begin_QOS_statistics\n";
-  *env << "server_availability\t" << (statusCode == 1 ? 0 : 100) << "\n";
-  *env << "stream_availability\t" << (statusCode == 0 ? 100 : 0) << "\n";
-
+  
   // Print out stats for each active subsession:
   qosMeasurementRecord* curQOSRecord = qosRecordHead;
   if (session != NULL) {
@@ -1103,23 +1019,20 @@ void printQOSData(int exitCode) {
     MediaSubsession* subsession;
     while ((subsession = iter.next()) != NULL) {
       RTPSource* src = subsession->rtpSource();
-#ifdef SUPPORT_REAL_RTSP
-      if (session->isRealNetworksRDT) src = (RTPSource*)(subsession->readSource()); // hack
-#endif
       if (src == NULL) continue;
-
+      
       *env << "subsession\t" << subsession->mediumName()
 	   << "/" << subsession->codecName() << "\n";
-
+      
       unsigned numPacketsReceived = 0, numPacketsExpected = 0;
-
+      
       if (curQOSRecord != NULL) {
 	numPacketsReceived = curQOSRecord->totNumPacketsReceived;
 	numPacketsExpected = curQOSRecord->totNumPacketsExpected;
       }
       *env << "num_packets_received\t" << numPacketsReceived << "\n";
       *env << "num_packets_lost\t" << numPacketsExpected - numPacketsReceived << "\n";
-
+      
       if (curQOSRecord != NULL) {
 	unsigned secsDiff = curQOSRecord->measurementEndTime.tv_sec
 	  - curQOSRecord->measurementStartTime.tv_sec;
@@ -1127,11 +1040,11 @@ void printQOSData(int exitCode) {
 	  - curQOSRecord->measurementStartTime.tv_usec;
 	double measurementTime = secsDiff + usecsDiff/1000000.0;
 	*env << "elapsed_measurement_time\t" << measurementTime << "\n";
-
+	
 	*env << "kBytes_received_total\t" << curQOSRecord->kBytesTotal << "\n";
-
+	
 	*env << "measurement_sampling_interval_ms\t" << qosMeasurementIntervalMS << "\n";
-
+	
 	if (curQOSRecord->kbits_per_second_max == 0) {
 	  // special case: we didn't receive any data:
 	  *env <<
@@ -1144,7 +1057,7 @@ void printQOSData(int exitCode) {
 	       << (measurementTime == 0.0 ? 0.0 : 8*curQOSRecord->kBytesTotal/measurementTime) << "\n";
 	  *env << "kbits_per_second_max\t" << curQOSRecord->kbits_per_second_max << "\n";
 	}
-
+	
 	*env << "packet_loss_percentage_min\t" << 100*curQOSRecord->packet_loss_fraction_min << "\n";
 	double packetLossFraction = numPacketsExpected == 0 ? 1.0
 	  : 1.0 - numPacketsReceived/(double)numPacketsExpected;
@@ -1152,35 +1065,20 @@ void printQOSData(int exitCode) {
 	*env << "packet_loss_percentage_ave\t" << 100*packetLossFraction << "\n";
 	*env << "packet_loss_percentage_max\t"
 	     << (packetLossFraction == 1.0 ? 100.0 : 100*curQOSRecord->packet_loss_fraction_max) << "\n";
-
-#ifdef SUPPORT_REAL_RTSP
-	if (session->isRealNetworksRDT) {
-	  RealRDTSource* rdt = (RealRDTSource*)src;
-	  *env << "inter_packet_gap_ms_min\t" << rdt->minInterPacketGapUS()/1000.0 << "\n";
-	  struct timeval totalGaps = rdt->totalInterPacketGaps();
+	
+	RTPReceptionStatsDB::Iterator statsIter(src->receptionStatsDB());
+	// Assume that there's only one SSRC source (usually the case):
+	RTPReceptionStats* stats = statsIter.next(True);
+	if (stats != NULL) {
+	  *env << "inter_packet_gap_ms_min\t" << stats->minInterPacketGapUS()/1000.0 << "\n";
+	  struct timeval totalGaps = stats->totalInterPacketGaps();
 	  double totalGapsMS = totalGaps.tv_sec*1000.0 + totalGaps.tv_usec/1000.0;
-	  unsigned totNumPacketsReceived = rdt->totNumPacketsReceived();
+	  unsigned totNumPacketsReceived = stats->totNumPacketsReceived();
 	  *env << "inter_packet_gap_ms_ave\t"
 	       << (totNumPacketsReceived == 0 ? 0.0 : totalGapsMS/totNumPacketsReceived) << "\n";
-	  *env << "inter_packet_gap_ms_max\t" << rdt->maxInterPacketGapUS()/1000.0 << "\n";
-	} else {
-#endif
-	  RTPReceptionStatsDB::Iterator statsIter(src->receptionStatsDB());
-	  // Assume that there's only one SSRC source (usually the case):
-	  RTPReceptionStats* stats = statsIter.next(True);
-	  if (stats != NULL) {
-	    *env << "inter_packet_gap_ms_min\t" << stats->minInterPacketGapUS()/1000.0 << "\n";
-	    struct timeval totalGaps = stats->totalInterPacketGaps();
-	    double totalGapsMS = totalGaps.tv_sec*1000.0 + totalGaps.tv_usec/1000.0;
-	    unsigned totNumPacketsReceived = stats->totNumPacketsReceived();
-	    *env << "inter_packet_gap_ms_ave\t"
-		 << (totNumPacketsReceived == 0 ? 0.0 : totalGapsMS/totNumPacketsReceived) << "\n";
-	    *env << "inter_packet_gap_ms_max\t" << stats->maxInterPacketGapUS()/1000.0 << "\n";
-	  }
-#ifdef SUPPORT_REAL_RTSP
+	  *env << "inter_packet_gap_ms_max\t" << stats->maxInterPacketGapUS()/1000.0 << "\n";
 	}
-#endif
-
+	
 	curQOSRecord = curQOSRecord->fNext;
       }
     }
diff --git a/testProgs/playSIP.cpp b/testProgs/playSIP.cpp
index 4e023dd..9f6ca5c 100644
--- a/testProgs/playSIP.cpp
+++ b/testProgs/playSIP.cpp
@@ -79,8 +79,6 @@ char* getSDPDescriptionFromURL(Medium* client, char const* url,
     result = sipClient->invite(url);
   }
 
-  extern unsigned statusCode;
-  statusCode = sipClient->inviteStatus();
   return result;
 }
 

-- 
liblivemedia packaging



More information about the pkg-multimedia-commits mailing list