[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