Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package live555 for openSUSE:Factory checked 
in at 2024-07-22 17:14:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/live555 (Old)
 and      /work/SRC/openSUSE:Factory/.live555.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "live555"

Mon Jul 22 17:14:18 2024 rev:41 rq:1188462 version:2024.06.26

Changes:
--------
--- /work/SRC/openSUSE:Factory/live555/live555.changes  2024-03-03 
20:19:32.662314621 +0100
+++ /work/SRC/openSUSE:Factory/.live555.new.17339/live555.changes       
2024-07-22 17:14:35.501098450 +0200
@@ -1,0 +2,50 @@
+Thu Jul 18 14:19:57 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 2024-06-26:
+  * Updated the "OnDemandServerMediaSubsession" implementation to
+    output an error message if the "sink->startPlaying()" call failed
+    (e.g., due to its source not being compatible with the sink).
+    This makes some common errors (e.g, a proper 'framer' not
+    being used) easier to detect.
+- update to 2024-05-30:
+  * Fixed a mistake that caused the config file
+    "config.raspberrypi" to not appear in the distribution.
+- update to 2024-05-15:
+  * Added a new config file "config.raspberrypi" that is known to
+    work for building the code on/for a Raspberry Pi 5.
+- update to 2024-05-05:
+  * Updated "QuickTimeFileSink" to add support for recording H.265
+    video streams.  (This is not fully working yet; it appears to
+    have some bugs.)
+- update to 2024-04-19:
+  * Updated "MPEG2TransportStreamFramer" to ignore big jumps (2x or
+    more) in the estimate for the duration of each Transport
+    packet.
+    This is likely caused by an unexpected jump in the PCR (not
+    indicated by "discontinuity_indicator").
+- update to 2024-03-08:
+  * Changed "ServerTLSState::setup()" (in "TLSState.cpp") to call
+    "SSL_CTX_use_certificate_chain_file()" instead of
+    "SSL_CTX_use_certificate_file()", to allow the server operator to
+    specify a chain of certificates, rather than just one.
+- update to 2024.02.28:
+  * Updated the code for "dateHeader()" (in "RTSPCommon.cpp") to
+    avoid using "strftime()", because that can produce a localized
+    date string that violates the RTSP specification
+    (which uses section 3.3.1 of RFC 2068 (the HTTP/1.1
+    specification) to define the "Date:" header).
+- update to 2024.02.23:
+  * Updated the code for "dateHeader()" (in "RTSPCommon.cpp") to use
+    "NULL" instead of "nullptr"; the latter was causing compilation
+    problems for someone.
+- update to 2024.02.15:
+  * Updated the RTCP implementation so that reception stats for a
+    SSRC are no longer deleted, even if a SSRC is reaped due to RTCP
+    inactivity (no RTCP "SR" reports received recently).
+
+-------------------------------------------------------------------
+Thu Jul 18 14:17:02 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 2024.
+
+-------------------------------------------------------------------

Old:
----
  live.2023.11.30.tar.gz

New:
----
  live.2024.06.26.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ live555.spec ++++++
--- /var/tmp/diff_new_pack.MPTQLL/_old  2024-07-22 17:14:36.257127807 +0200
+++ /var/tmp/diff_new_pack.MPTQLL/_new  2024-07-22 17:14:36.257127807 +0200
@@ -20,7 +20,7 @@
 %define lmdmaj 112
 
 Name:           live555
-Version:        2023.11.30
+Version:        2024.06.26
 Release:        0
 Summary:        LIVE555 Streaming Media
 License:        LGPL-2.1-only

++++++ live.2023.11.30.tar.gz -> live.2024.06.26.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp 
new/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp
--- old/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp    2023-11-30 
09:22:23.000000000 +0100
+++ new/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp    2024-06-26 
07:46:23.000000000 +0200
@@ -20,6 +20,11 @@
 #include "BasicUsageEnvironment.hh"
 #include <stdio.h>
 
+////////// library version constants //////////
+
+extern char const* const BasicUsageEnvironmentLibraryVersionStr = 
BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING;
+extern int const BasicUsageEnvironmentLibraryVersionInt = 
BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT;
+
 ////////// BasicUsageEnvironment //////////
 
 #if defined(__WIN32__) || defined(_WIN32)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh 
new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
--- old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh     
2023-11-30 09:22:23.000000000 +0100
+++ new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh     
2024-06-26 07:46:23.000000000 +0200
@@ -14,12 +14,15 @@
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **********/
 // Version information for the "BasicUsageEnvironment" library
-// Copyright (c) 1996-2023 Live Networks, Inc.  All rights reserved.
+// Copyright (c) 1996-2024 Live Networks, Inc.  All rights reserved.
 
 #ifndef _BASICUSAGEENVIRONMENT_VERSION_HH
 #define _BASICUSAGEENVIRONMENT_VERSION_HH
 
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING   "2023.11.30"
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT              1701302400
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING   "2024.06.26"
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT              1719360000
+
+extern char const* const BasicUsageEnvironmentLibraryVersionStr;
+extern int const BasicUsageEnvironmentLibraryVersionInt;
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/UsageEnvironment/UsageEnvironment.cpp 
new/live/UsageEnvironment/UsageEnvironment.cpp
--- old/live/UsageEnvironment/UsageEnvironment.cpp      2023-11-30 
09:22:23.000000000 +0100
+++ new/live/UsageEnvironment/UsageEnvironment.cpp      2024-06-26 
07:46:23.000000000 +0200
@@ -19,6 +19,13 @@
 
 #include "UsageEnvironment.hh"
 
+////////// library version constants //////////
+
+extern char const* const UsageEnvironmentLibraryVersionStr = 
USAGEENVIRONMENT_LIBRARY_VERSION_STRING;
+extern int const UsageEnvironmentLibraryVersionInt = 
USAGEENVIRONMENT_LIBRARY_VERSION_INT;
+
+////////// UsageEnvironment //////////
+
 Boolean UsageEnvironment::reclaim() {
   // We delete ourselves only if we have no remainining state:
   if (liveMediaPriv == NULL && groupsockPriv == NULL) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/live/UsageEnvironment/include/UsageEnvironment_version.hh 
new/live/UsageEnvironment/include/UsageEnvironment_version.hh
--- old/live/UsageEnvironment/include/UsageEnvironment_version.hh       
2023-11-30 09:22:23.000000000 +0100
+++ new/live/UsageEnvironment/include/UsageEnvironment_version.hh       
2024-06-26 07:46:23.000000000 +0200
@@ -14,12 +14,15 @@
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **********/
 // Version information for the "UsageEnvironment" library
-// Copyright (c) 1996-2023 Live Networks, Inc.  All rights reserved.
+// Copyright (c) 1996-2024 Live Networks, Inc.  All rights reserved.
 
 #ifndef _USAGEENVIRONMENT_VERSION_HH
 #define _USAGEENVIRONMENT_VERSION_HH
 
-#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING        "2023.11.30"
-#define USAGEENVIRONMENT_LIBRARY_VERSION_INT           1701302400
+#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING        "2024.06.26"
+#define USAGEENVIRONMENT_LIBRARY_VERSION_INT           1719360000
+
+extern char const* const UsageEnvironmentLibraryVersionStr;
+extern int const UsageEnvironmentLibraryVersionInt;
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/config.linux-with-shared-libraries 
new/live/config.linux-with-shared-libraries
--- old/live/config.linux-with-shared-libraries 2023-11-30 09:22:51.000000000 
+0100
+++ new/live/config.linux-with-shared-libraries 2024-06-26 07:46:35.000000000 
+0200
@@ -3,24 +3,24 @@
 # At least one interface changes, or is removed => CURRENT += 1; REVISION = 0; 
AGE = 0
 # One or more interfaces were added, but no existing interfaces were changed 
or removed => CURRENT += 1; REVISION = 0; AGE += 1
 
-libliveMedia_VERSION_CURRENT=112
-libliveMedia_VERSION_REVISION=0
-libliveMedia_VERSION_AGE=0
+libliveMedia_VERSION_CURRENT=113
+libliveMedia_VERSION_REVISION=3
+libliveMedia_VERSION_AGE=1
 libliveMedia_LIB_SUFFIX=so.$(shell expr $(libliveMedia_VERSION_CURRENT) - 
$(libliveMedia_VERSION_AGE)).$(libliveMedia_VERSION_AGE).$(libliveMedia_VERSION_REVISION)
 
-libBasicUsageEnvironment_VERSION_CURRENT=2
-libBasicUsageEnvironment_VERSION_REVISION=4
-libBasicUsageEnvironment_VERSION_AGE=0
+libBasicUsageEnvironment_VERSION_CURRENT=3
+libBasicUsageEnvironment_VERSION_REVISION=0
+libBasicUsageEnvironment_VERSION_AGE=1
 libBasicUsageEnvironment_LIB_SUFFIX=so.$(shell expr 
$(libBasicUsageEnvironment_VERSION_CURRENT) - 
$(libBasicUsageEnvironment_VERSION_AGE)).$(libBasicUsageEnvironment_VERSION_AGE).$(libBasicUsageEnvironment_VERSION_REVISION)
 
-libUsageEnvironment_VERSION_CURRENT=4
+libUsageEnvironment_VERSION_CURRENT=5
 libUsageEnvironment_VERSION_REVISION=0
-libUsageEnvironment_VERSION_AGE=1
+libUsageEnvironment_VERSION_AGE=2
 libUsageEnvironment_LIB_SUFFIX=so.$(shell expr 
$(libUsageEnvironment_VERSION_CURRENT) - 
$(libUsageEnvironment_VERSION_AGE)).$(libUsageEnvironment_VERSION_AGE).$(libUsageEnvironment_VERSION_REVISION)
 
-libgroupsock_VERSION_CURRENT=31
-libgroupsock_VERSION_REVISION=13
-libgroupsock_VERSION_AGE=1
+libgroupsock_VERSION_CURRENT=32
+libgroupsock_VERSION_REVISION=0
+libgroupsock_VERSION_AGE=2
 libgroupsock_LIB_SUFFIX=so.$(shell expr $(libgroupsock_VERSION_CURRENT) - 
$(libgroupsock_VERSION_AGE)).$(libgroupsock_VERSION_AGE).$(libgroupsock_VERSION_REVISION)
 #####
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/config.raspberrypi new/live/config.raspberrypi
--- old/live/config.raspberrypi 1970-01-01 01:00:00.000000000 +0100
+++ new/live/config.raspberrypi 2024-06-26 07:46:35.000000000 +0200
@@ -0,0 +1,17 @@
+COMPILE_OPTS =         $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t 
-D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DNO_OPENSSL=1 -DNO_STD_LIB=1
+C =                    c
+C_COMPILER =           cc
+C_FLAGS =              $(COMPILE_OPTS) $(CPPFLAGS) $(CFLAGS)
+CPP =                  cpp
+CPLUSPLUS_COMPILER =   c++
+CPLUSPLUS_FLAGS =      $(COMPILE_OPTS) -Wall -DBSD=1 $(CPPFLAGS) $(CXXFLAGS)
+OBJ =                  o
+LINK =                 c++ -o
+LINK_OPTS =            -L. $(LDFLAGS)
+CONSOLE_LINK_OPTS =    $(LINK_OPTS)
+LIBRARY_LINK =         ar cr 
+LIBRARY_LINK_OPTS =    
+LIB_SUFFIX =                   a
+LIBS_FOR_CONSOLE_APPLICATION =
+LIBS_FOR_GUI_APPLICATION =
+EXE =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/groupsock/Groupsock.cpp 
new/live/groupsock/Groupsock.cpp
--- old/live/groupsock/Groupsock.cpp    2023-11-30 09:22:23.000000000 +0100
+++ new/live/groupsock/Groupsock.cpp    2024-06-26 07:46:23.000000000 +0200
@@ -25,6 +25,11 @@
 #endif
 #include <stdio.h>
 
+////////// library version constants //////////
+
+extern char const* const groupsockLibraryVersionStr = 
GROUPSOCK_LIBRARY_VERSION_STRING;
+extern int const groupsockLibraryVersionInt = GROUPSOCK_LIBRARY_VERSION_INT;
+
 ///////// OutputSocket //////////
 
 OutputSocket::OutputSocket(UsageEnvironment& env, int family)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/groupsock/include/groupsock_version.hh 
new/live/groupsock/include/groupsock_version.hh
--- old/live/groupsock/include/groupsock_version.hh     2023-11-30 
09:22:23.000000000 +0100
+++ new/live/groupsock/include/groupsock_version.hh     2024-06-26 
07:46:23.000000000 +0200
@@ -14,12 +14,15 @@
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **********/
 // Version information for the "groupsock" library
-// Copyright (c) 1996-2023 Live Networks, Inc.  All rights reserved.
+// Copyright (c) 1996-2024 Live Networks, Inc.  All rights reserved.
 
 #ifndef _GROUPSOCK_VERSION_HH
 #define _GROUPSOCK_VERSION_HH
 
-#define GROUPSOCK_LIBRARY_VERSION_STRING       "2023.11.30"
-#define GROUPSOCK_LIBRARY_VERSION_INT          1701302400
+#define GROUPSOCK_LIBRARY_VERSION_STRING       "2024.06.26"
+#define GROUPSOCK_LIBRARY_VERSION_INT          1719360000
+
+extern char const* const groupsockLibraryVersionStr;
+extern int const groupsockLibraryVersionInt;
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MPEG2TransportStreamFramer.cpp 
new/live/liveMedia/MPEG2TransportStreamFramer.cpp
--- old/live/liveMedia/MPEG2TransportStreamFramer.cpp   2023-11-30 
09:22:23.000000000 +0100
+++ new/live/liveMedia/MPEG2TransportStreamFramer.cpp   2024-06-26 
07:46:23.000000000 +0200
@@ -257,7 +257,8 @@
 
     if (fTSPacketDurationEstimate == 0.0) { // we've just started
       fTSPacketDurationEstimate = durationPerPacket;
-    } else if (discontinuity_indicator == 0 && durationPerPacket >= 0.0) {
+    } else if (discontinuity_indicator == 0 && durationPerPacket >= 0.0
+              && durationPerPacket < 2*fTSPacketDurationEstimate) {
       fTSPacketDurationEstimate
        = durationPerPacket*NEW_DURATION_WEIGHT
        + fTSPacketDurationEstimate*(1-NEW_DURATION_WEIGHT);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/Media.cpp new/live/liveMedia/Media.cpp
--- old/live/liveMedia/Media.cpp        2023-11-30 09:22:23.000000000 +0100
+++ new/live/liveMedia/Media.cpp        2024-06-26 07:46:23.000000000 +0200
@@ -21,6 +21,11 @@
 #include "Media.hh"
 #include "HashTable.hh"
 
+////////// library version constants //////////
+
+extern char const* const liveMediaLibraryVersionStr = 
LIVEMEDIA_LIBRARY_VERSION_STRING;
+extern int const liveMediaLibraryVersionInt = LIVEMEDIA_LIBRARY_VERSION_INT;
+
 ////////// Medium //////////
 
 Medium::Medium(UsageEnvironment& env)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/OnDemandServerMediaSubsession.cpp 
new/live/liveMedia/OnDemandServerMediaSubsession.cpp
--- old/live/liveMedia/OnDemandServerMediaSubsession.cpp        2023-11-30 
09:22:23.000000000 +0100
+++ new/live/liveMedia/OnDemandServerMediaSubsession.cpp        2024-06-26 
07:46:23.000000000 +0200
@@ -571,13 +571,17 @@
   }
 
   if (!fAreCurrentlyPlaying && fMediaSource != NULL) {
-    if (fRTPSink != NULL) {
-      fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
-      fAreCurrentlyPlaying = True;
-    } else if (fUDPSink != NULL) {
-      fUDPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
-      fAreCurrentlyPlaying = True;
+    MediaSink* sink;
+    if (fRTPSink != NULL) { sink = fRTPSink; }
+    else if (fUDPSink != NULL) { sink = fUDPSink; }
+    else return;
+    
+    if (!sink->startPlaying(*fMediaSource, afterPlayingStreamState, this)) {
+      fMediaSource->envir() << "sink->startPlaying() failed: "
+                           << fMediaSource->envir().getResultMsg() << "\n";
+      return;
     }
+    fAreCurrentlyPlaying = True;
   }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/QuickTimeFileSink.cpp 
new/live/liveMedia/QuickTimeFileSink.cpp
--- old/live/liveMedia/QuickTimeFileSink.cpp    2023-11-30 09:22:23.000000000 
+0100
+++ new/live/liveMedia/QuickTimeFileSink.cpp    2024-06-26 07:46:23.000000000 
+0200
@@ -26,13 +26,15 @@
 #include "H263plusVideoRTPSource.hh" // for the special header
 #include "MPEG4GenericRTPSource.hh" //for 
"samplingFrequencyFromAudioSpecificConfig()"
 #include "MPEG4LATMAudioRTPSource.hh" // for "parseGeneralConfigStr()"
+#include "H264or5VideoStreamFramer.hh" // for "removeH264or5EmulationBytes()"
 #include "Base64.hh"
 
 #include <ctype.h>
 
 #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
+#define H264_IDR_FRAME 0x65  //bit 8 == 0, bits 7-6 (ref) == 3, bits 5-1 
(type) == 5
+#define isIDRFrame(firstByte) (firstByte == H264_IDR_FRAME || 
((firstByte&0x7E)>>1) == 19 || ((firstByte&0x7E)>>1) == 20)
 
 ////////// SubsessionIOState, ChunkDescriptor ///////////
 // A structure used to represent the I/O state of each input 'subsession':
@@ -653,6 +655,10 @@
        fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_avc1;
        fQTTimeScale = 600;
        fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS;
+      } else if (strcmp(fOurSubsession.codecName(), "H265") == 0) {
+       fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_hvc1;
+       fQTTimeScale = 600;
+       fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS;
       } else if (strcmp(fOurSubsession.codecName(), "MP4V-ES") == 0) {
        fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_mp4v;
        fQTTimeScale = 600;
@@ -801,7 +807,10 @@
   struct timeval const& presentationTime = buffer.presentationTime();
   int64_t const destFileOffset = TellFile64(fOurSink.fOutFid);
   unsigned sampleNumberOfFrameStart = fQTTotNumSamples + 1;
-  Boolean avcHack = fQTMediaDataAtomCreator == 
&QuickTimeFileSink::addAtom_avc1;
+  Boolean h264or5Hack =
+    fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_avc1 ||
+    fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_hvc1;
+    
 
   // If we're not syncing streams, or this subsession is not video, then
   // just give this frame a fixed duration:
@@ -809,7 +818,7 @@
       || fQTcomponentSubtype != fourChar('v','i','d','e')) {
     unsigned const frameDuration = fQTTimeUnitsPerSample*fQTSamplesPerFrame;
     unsigned frameSizeToUse = frameSize;
-    if (avcHack) frameSizeToUse += 4; // H.264/AVC gets the frame size prefix
+    if (h264or5Hack) frameSizeToUse += 4; // H.264/5 gets the frame size prefix
 
     fQTTotNumSamples += useFrame1(frameSizeToUse, presentationTime, 
frameDuration, destFileOffset);
   } else {
@@ -825,7 +834,7 @@
       unsigned frameDuration
        = (unsigned)((2*duration*fQTTimeScale+1)/2); // round
       unsigned frameSizeToUse = fPrevFrameState.frameSize;
-      if (avcHack) frameSizeToUse += 4; // H.264/AVC gets the frame size prefix
+      if (h264or5Hack) frameSizeToUse += 4; // H.264/5 gets the frame size 
prefix
 
       unsigned numSamples
        = useFrame1(frameSizeToUse, ppt, frameDuration, 
fPrevFrameState.destFileOffset);
@@ -833,7 +842,7 @@
       sampleNumberOfFrameStart = fQTTotNumSamples + 1;
     }
 
-    if (avcHack && (*frameSource == H264_IDR_FRAME)) {
+    if (h264or5Hack && isIDRFrame(*frameSource)) {
       SyncFrame* newSyncFrame = new SyncFrame(fQTTotNumSamples + 1);
       if (fTailSyncFrame == NULL) {
         fHeadSyncFrame = newSyncFrame;
@@ -849,7 +858,7 @@
     fPrevFrameState.destFileOffset = destFileOffset;
   }
 
-  if (avcHack) fOurSink.addWord(frameSize);
+  if (h264or5Hack) fOurSink.addWord(frameSize);
 
   // Write the data into the file:
   fwrite(frameSource, 1, frameSize, fOurSink.fOutFid);
@@ -1119,7 +1128,7 @@
 
          // 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;
+         if (!isIDRFrame(*frameSource)) return False;
        }
        // But now we are
        fHaveBeenSynced = True;
@@ -1888,45 +1897,165 @@
 addAtomEnd;
 
 addAtom(avcC);
-// Begin by Base-64 decoding the "sprop" parameter sets strings:
+  // Begin by Base-64 decoding the "sprop" parameter sets strings:
   char* psets = 
strDup(fCurrentIOState->fOurSubsession.fmtp_spropparametersets());
   if (psets == NULL) return 0;
 
+  char const* spsBase64 = psets;
   size_t comma_pos = strcspn(psets, ",");
   psets[comma_pos] = '\0';
-  char const* sps_b64 = psets;
-  char const* pps_b64 = &psets[comma_pos+1];
-  unsigned sps_count;
-  unsigned char* sps_data = base64Decode(sps_b64, sps_count, false);
-  unsigned pps_count;
-  unsigned char* pps_data = base64Decode(pps_b64, pps_count, false);
 
-// Then add the decoded data:
+  char const* ppsBase64 = &psets[comma_pos+1];
+
+  unsigned spsSize;
+  unsigned char* sps = base64Decode(spsBase64, spsSize, false);
+
+  unsigned ppsSize;
+  unsigned char* pps = base64Decode(ppsBase64, ppsSize, false);
+
+  // We use some of the data from the "SPS". Remove any 'emulation bytes' from 
it first:
+  if (spsSize == 0) return 0;
+  u_int8_t* spsWEB = new u_int8_t[spsSize]; // "WEB" means "Without Emulation 
Bytes"
+  unsigned spsWEBSize = removeH264or5EmulationBytes(spsWEB, spsSize, sps, 
spsSize);
+  if (spsWEBSize < 4) { // Bad SPS size
+    delete[] spsWEB;
+    return 0;
+  }
+
+  // Then add the decoded data:
   size += addByte(0x01); // configuration version
-  size += addByte(sps_data[1]); // profile
-  size += addByte(sps_data[2]); // profile compat
-  size += addByte(sps_data[3]); // level
+  size += addByte(spsWEB[1]); // profile
+  size += addByte(spsWEB[2]); // profile compat
+  size += addByte(spsWEB[3]); // level
   size += addByte(0xff); /* 0b11111100 | lengthsize = 0x11 */
-  size += addByte(0xe0 | (sps_count > 0 ? 1 : 0) );
-  if (sps_count > 0) {
-    size += addHalfWord(sps_count);
-    for (unsigned i = 0; i < sps_count; i++) {
-      size += addByte(sps_data[i]);
+  size += addByte(0xe0 | (spsSize > 0 ? 1 : 0) );
+  if (spsSize > 0) {
+    size += addHalfWord(spsSize);
+    for (unsigned i = 0; i < spsSize; i++) {
+      size += addByte(sps[i]);
     }
   }
-  size += addByte(pps_count > 0 ? 1 : 0);
-  if (pps_count > 0) {
-    size += addHalfWord(pps_count);
-    for (unsigned i = 0; i < pps_count; i++) {
-      size += addByte(pps_data[i]);
+  size += addByte(ppsSize > 0 ? 1 : 0);
+  if (ppsSize > 0) {
+    size += addHalfWord(ppsSize);
+    for (unsigned i = 0; i < ppsSize; i++) {
+      size += addByte(pps[i]);
     }
   }
 
-// Finally, delete the data that we allocated:
-  delete[] pps_data; delete[] sps_data;
+  // Finally, delete the data that we allocated:
+  delete[] spsWEB;
+  delete[] pps; delete[] sps;
   delete[] psets;
 addAtomEnd;
 
+addAtom(hvc1);
+// General sample description fields:
+  size += addWord(0x00000000); // Reserved
+  size += addWord(0x00000001); // Reserved+Data       reference index
+// Video sample       description     fields:
+  size += addWord(0x00000000); // Version+Revision level
+  size += add4ByteString("appl"); // Vendor
+  size += addWord(0x00000000); // Temporal quality
+  size += addWord(0x00000000); // Spatial quality
+  unsigned const widthAndHeight       = (fMovieWidth<<16)|fMovieHeight;
+  size += addWord(widthAndHeight); // Width+height
+  size += addWord(0x00480000); // Horizontal resolution
+  size += addWord(0x00480000); // Vertical resolution
+  size += addWord(0x00000000); // Data size
+  size += addWord(0x00010548); // Frame count+Compressor name (start)
+    // "H.265"
+  size += addWord(0x2e323635); // Compressor name (continued)
+  size += addZeroWords(6); // Compressor name (continued - zero)
+  size += addWord(0x00000018); // Compressor name (final)+Depth
+  size += addHalfWord(0xffff); // Color table id
+  size += addAtom_hvcC();
+addAtomEnd;
+
+addAtom(hvcC);
+  // Begin by Base-64 decoding the "sprop" parameter sets strings:
+  char const* vpsBase64 = 
strDup(fCurrentIOState->fOurSubsession.fmtp_spropvps());
+  char const* spsBase64 = 
strDup(fCurrentIOState->fOurSubsession.fmtp_spropsps());
+  char const* ppsBase64 = 
strDup(fCurrentIOState->fOurSubsession.fmtp_sproppps());
+  if (vpsBase64 == NULL || spsBase64 == NULL || ppsBase64 == NULL) return 0;
+
+  unsigned vpsSize;
+  unsigned char* vps = base64Decode(vpsBase64, vpsSize, false);
+
+  unsigned spsSize;
+  unsigned char* sps = base64Decode(spsBase64, spsSize, false);
+
+  unsigned ppsSize;
+  unsigned char* pps = base64Decode(ppsBase64, ppsSize, false);
+
+  // We use some of the data from the "VPS". Remove any 'emulation bytes' from 
it first:
+  if (vpsSize == 0) return 0;
+  u_int8_t* vpsWEB = new u_int8_t[vpsSize]; // "WEB" means "Without Emulation 
Bytes"
+  unsigned vpsWEBSize = removeH264or5EmulationBytes(vpsWEB, vpsSize, vps, 
vpsSize);
+  if (vpsWEBSize < 6/*'profile_tier_level' offset*/ + 12/*num 
'profile_tier_level' bytes*/) {
+    // Bad VPS size
+    delete[] vpsWEB;
+    return 0;
+  }
+
+  // Then add the decoded data:
+  size += addByte(0x01); // configurationVersion = 1
+
+  u_int8_t const* profileTierLevelHeaderBytes = &vpsWEB[6];
+  size += addByte(profileTierLevelHeaderBytes[0]);
+      // general_profile_space + general_tier_flag + general_profile_idc
+
+  u_int8_t const* general_profile_compatibility_flags = 
&profileTierLevelHeaderBytes[1];
+  for (unsigned i = 0; i < 4; ++i) size += 
addByte(general_profile_compatibility_flags[i]);
+      // general_profile_compatibility_flags
+
+  u_int8_t const* general_constraint_indicator_flags = 
&profileTierLevelHeaderBytes[5];
+  for (unsigned i = 0; i < 6; ++i) size += 
addByte(general_constraint_indicator_flags[i]);
+      // general_constraint_indicator_flags
+
+  size += addByte(profileTierLevelHeaderBytes[11]); // general_level_idc
+  size += addHalfWord(0xF000); // min_spatial_segmentation_idc = 0 ???
+  size += addByte(0xFC); // parallelismType = 0 ???
+  size += addByte(0xFD); // chroma_format_idc = 1 ???
+  size += addByte(0xF8); // bit_depth_luma_minus8 = 0 ???
+  size += addByte(0xF8); // bit_depth_chroma_minus8 = 0 ???
+  size += addHalfWord(0x0000); // avgFrameRate = 0
+  size += addByte(0x0F);
+      // constantFrameRate = 0; numTemporalLayers = 1; temporalIdNested = 1; 
lengthSizeMinusOne = 3 ???
+  size += addByte(1 + (spsSize > 0) + (ppsSize > 0)); // numOfArrays
+
+  if (vpsSize > 0) {
+    size += addByte(0x20); // array_completeness = 0; NAL_unit_type = VPS
+    size += addHalfWord(1); // numNalus
+    size += addHalfWord(vpsSize);
+    for (unsigned i = 0; i < vpsSize; i++) {
+      size += addByte(vps[i]);
+    }
+  }
+
+  if (spsSize > 0) {
+    size += addByte(0x21); // array_completeness = 0; NAL_unit_type = SPS
+    size += addHalfWord(1); // numNalus
+    size += addHalfWord(spsSize);
+    for (unsigned i = 0; i < spsSize; i++) {
+      size += addByte(sps[i]);
+    }
+  }
+
+  if (ppsSize > 0) {
+    size += addByte(0x22); // array_completeness = 0; NAL_unit_type = PPS
+    size += addHalfWord(1); // numNalus
+    size += addHalfWord(ppsSize);
+    for (unsigned i = 0; i < ppsSize; i++) {
+      size += addByte(pps[i]);
+    }
+  }
+
+// Finally, delete the data that we allocated:
+  delete[] vpsWEB;
+  delete[] vps; delete[] pps; delete[] sps;
+addAtomEnd;
+
 addAtom(mp4v);
 // General sample description fields:
   size += addWord(0x00000000); // Reserved
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTCP.cpp new/live/liveMedia/RTCP.cpp
--- old/live/liveMedia/RTCP.cpp 2023-11-30 09:22:23.000000000 +0100
+++ new/live/liveMedia/RTCP.cpp 2024-06-26 07:46:23.000000000 +0200
@@ -102,7 +102,7 @@
 #ifdef DEBUG
         fprintf(stderr, "reap: removing SSRC 0x%x\n", oldSSRC);
 #endif
-       fOurRTCPInstance.removeSSRC(oldSSRC, True);
+       fOurRTCPInstance.removeSSRC(oldSSRC, False/*keep stats around*/);
     }
   } while (foundOldMember);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTSPClient.cpp 
new/live/liveMedia/RTSPClient.cpp
--- old/live/liveMedia/RTSPClient.cpp   2023-11-30 09:22:23.000000000 +0100
+++ new/live/liveMedia/RTSPClient.cpp   2024-06-26 07:46:23.000000000 +0200
@@ -419,7 +419,6 @@
 
   // Set the "User-Agent:" header to use in each request:
   char const* const libName = "LIVE555 Streaming Media v";
-  char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING;
   char const* libPrefix; char const* libSuffix;
   if (applicationName == NULL || applicationName[0] == '\0') {
     applicationName = libPrefix = libSuffix = "";
@@ -428,9 +427,9 @@
     libSuffix = ")";
   }
   unsigned userAgentNameSize
-    = strlen(applicationName) + strlen(libPrefix) + strlen(libName) + 
strlen(libVersionStr) + strlen(libSuffix) + 1;
+    = strlen(applicationName) + strlen(libPrefix) + strlen(libName) + 
strlen(liveMediaLibraryVersionStr) + strlen(libSuffix) + 1;
   char* userAgentName = new char[userAgentNameSize];
-  sprintf(userAgentName, "%s%s%s%s%s", applicationName, libPrefix, libName, 
libVersionStr, libSuffix);
+  sprintf(userAgentName, "%s%s%s%s%s", applicationName, libPrefix, libName, 
liveMediaLibraryVersionStr, libSuffix);
   setUserAgentString(userAgentName);
   delete[] userAgentName;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTSPCommon.cpp 
new/live/liveMedia/RTSPCommon.cpp
--- old/live/liveMedia/RTSPCommon.cpp   2023-11-30 09:22:23.000000000 +0100
+++ new/live/liveMedia/RTSPCommon.cpp   2024-06-26 07:46:23.000000000 +0200
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h> // for "isxdigit()
-#include <time.h> // for "strftime()" and "gmtime()"
+#include <time.h> // for "gmtime()"
 
 static void decodeURL(char* url) {
   // Replace (in place) any %<hex><hex> sequences with the appropriate 8-bit 
character.
@@ -361,13 +361,19 @@
       time_tm = tm{};
   }
 #else
-  if (gmtime_r(&tt, &time_tm) == nullptr) {
+  if (gmtime_r(&tt, &time_tm) == NULL) {
     time_tm = tm();
   }
 #endif
-  strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", &time_tm);
+  static const char* day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 
};
+  static const char* month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+  snprintf(buf, sizeof buf, "Date: %s, %s %02d %04d %02d:%02d:%02d GMT\r\n",
+          day[time_tm.tm_wday], month[time_tm.tm_mon], time_tm.tm_mday,
+          1900 + time_tm.tm_year,
+          time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec);
 #else
-  // WinCE apparently doesn't have "time()", "strftime()", or "gmtime()",
+  // WinCE apparently doesn't have "time()", or "gmtime()",
   // so generate the "Date:" header a different, WinCE-specific way.
   // (Thanks to Pierre l'Hussiez for this code)
   // RSF: But where is the "Date: " string?  This code doesn't look quite 
right...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTSPCommon.cpp.new 
new/live/liveMedia/RTSPCommon.cpp.new
--- old/live/liveMedia/RTSPCommon.cpp.new       1970-01-01 01:00:00.000000000 
+0100
+++ new/live/liveMedia/RTSPCommon.cpp.new       2024-06-26 07:46:23.000000000 
+0200
@@ -0,0 +1,396 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2024 Live Networks, Inc.  All rights reserved.
+// Common routines used by both RTSP clients and servers
+// Implementation
+
+#include "RTSPCommon.hh"
+#include "Locale.hh"
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h> // for "isxdigit()
+#include <time.h> // for "gmtime()"
+
+static void decodeURL(char* url) {
+  // Replace (in place) any %<hex><hex> sequences with the appropriate 8-bit 
character.
+  char* cursor = url;
+  while (*cursor) {
+    if ((cursor[0] == '%') &&
+       cursor[1] && isxdigit(cursor[1]) &&
+       cursor[2] && isxdigit(cursor[2])) {
+      // We saw a % followed by 2 hex digits, so we copy the literal hex value 
into the URL, then advance the cursor past it:
+      char hex[3];
+      hex[0] = cursor[1];
+      hex[1] = cursor[2];
+      hex[2] = '\0';
+      *url++ = (char)strtol(hex, NULL, 16);
+      cursor += 3;
+    } else {
+      // Common case: This is a normal character or a bogus % expression, so 
just copy it
+      *url++ = *cursor++;
+    }
+  }
+  
+  *url = '\0';
+}
+
+Boolean parseRTSPRequestString(char const* reqStr, unsigned reqStrSize,
+                              char* resultCmdName,
+                              unsigned resultCmdNameMaxSize,
+                              char* resultURLPreSuffix,
+                              unsigned resultURLPreSuffixMaxSize,
+                              char* resultURLSuffix,
+                              unsigned resultURLSuffixMaxSize,
+                              char* resultCSeq,
+                              unsigned resultCSeqMaxSize,
+                               char* resultSessionIdStr,
+                               unsigned resultSessionIdStrMaxSize,
+                              unsigned& contentLength, Boolean& urlIsRTSPS) {
+  // This parser is currently rather dumb; it should be made smarter #####
+  urlIsRTSPS = False; // by default
+
+  // "Be liberal in what you accept": Skip over any whitespace at the start of 
the request:
+  unsigned i;
+  for (i = 0; i < reqStrSize; ++i) {
+    char c = reqStr[i];
+    if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\0')) break;
+  }
+  if (i == reqStrSize) return False; // The request consisted of nothing but 
whitespace!
+
+  // Then read everything up to the next space (or tab) as the command name:
+  Boolean parseSucceeded = False;
+  unsigned i1 = 0;
+  for (; i1 < resultCmdNameMaxSize-1 && i < reqStrSize; ++i,++i1) {
+    char c = reqStr[i];
+    if (c == ' ' || c == '\t') {
+      parseSucceeded = True;
+      break;
+    }
+
+    resultCmdName[i1] = c;
+  }
+  resultCmdName[i1] = '\0';
+  if (!parseSucceeded) return False;
+
+  // Skip over the prefix of any "rtsp://" or "rtsp:/" (or "rtsps://" or 
"rtsps:/")
+  // URL that follows:
+  unsigned j = i+1;
+  while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // 
skip over any additional white space
+  for (; (int)j < (int)(reqStrSize-8); ++j) {
+    if ((reqStr[j] == 'r' || reqStr[j] == 'R')
+       && (reqStr[j+1] == 't' || reqStr[j+1] == 'T')
+       && (reqStr[j+2] == 's' || reqStr[j+2] == 'S')
+       && (reqStr[j+3] == 'p' || reqStr[j+3] == 'P')) {
+      if (reqStr[j+4] == 's' || reqStr[j+4] == 'S') {
+       urlIsRTSPS = True;
+       ++j;
+      }
+      if (reqStr[j+4] == ':' && reqStr[j+5] == '/') {
+       j += 6;
+       if (reqStr[j] == '/') {
+         // This is a "rtsp(s)://" URL; skip over the host:port part that 
follows:
+         ++j;
+         while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j;
+       } else {
+         // This is a "rtsp(s):/" URL; back up to the "/":
+         --j;
+       }
+       i = j;
+       break;
+      }
+    }
+  }    
+
+  // Look for the URL suffix (before the following "RTSP/"):
+  parseSucceeded = False;
+  for (unsigned k = i+1; (int)k < (int)(reqStrSize-5); ++k) {
+    if (reqStr[k] == 'R' && reqStr[k+1] == 'T' &&
+       reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') {
+      while (--k >= i && reqStr[k] == ' ') {} // go back over all spaces 
before "RTSP/"
+      unsigned k1 = k;
+      while (k1 > i && reqStr[k1] != '/') --k1;
+
+      // ASSERT: At this point
+      //   i: first space or slash after "host" or "host:port"
+      //   k: last non-space before "RTSP/"
+      //   k1: last slash in the range [i,k]
+
+      // The URL suffix comes from [k1+1,k]
+      // Copy "resultURLSuffix":
+      unsigned n = 0, k2 = k1+1;
+      if (k2 <= k) {
+        if (k - k1 + 1 > resultURLSuffixMaxSize) return False; // there's no 
room
+        while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++];
+      }
+      resultURLSuffix[n] = '\0';
+
+      // The URL 'pre-suffix' comes from [i+1,k1-1]
+      // Copy "resultURLPreSuffix":
+      n = 0; k2 = i+1;
+      if (k2+1 <= k1) {
+        if (k1 - i > resultURLPreSuffixMaxSize) return False; // there's no 
room
+        while (k2 <= k1-1) resultURLPreSuffix[n++] = reqStr[k2++];
+      }
+      resultURLPreSuffix[n] = '\0';
+      decodeURL(resultURLPreSuffix);
+
+      i = k + 7; // to go past " RTSP/"
+      parseSucceeded = True;
+      break;
+    }
+  }
+  if (!parseSucceeded) return False;
+
+  // Look for "CSeq:" (mandatory, case insensitive), skip whitespace,
+  // then read everything up to the next \r or \n as 'CSeq':
+  parseSucceeded = False;
+  for (j = i; (int)j < (int)(reqStrSize-5); ++j) {
+    if (_strncasecmp("CSeq:", &reqStr[j], 5) == 0) {
+      j += 5;
+      while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
+      unsigned n;
+      for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) {
+       char c = reqStr[j];
+       if (c == '\r' || c == '\n') {
+         parseSucceeded = True;
+         break;
+       }
+
+       resultCSeq[n] = c;
+      }
+      resultCSeq[n] = '\0';
+      break;
+    }
+  }
+  if (!parseSucceeded) return False;
+
+  // Look for "Session:" (optional, case insensitive), skip whitespace,
+  // then read everything up to the next \r or \n as 'Session':
+  resultSessionIdStr[0] = '\0'; // default value (empty string)
+  for (j = i; (int)j < (int)(reqStrSize-8); ++j) {
+    if (_strncasecmp("Session:", &reqStr[j], 8) == 0) {
+      j += 8;
+      while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
+      unsigned n;
+      for (n = 0; n < resultSessionIdStrMaxSize-1 && j < reqStrSize; ++n,++j) {
+       char c = reqStr[j];
+       if (c == '\r' || c == '\n') {
+         break;
+       }
+
+       resultSessionIdStr[n] = c;
+      }
+      resultSessionIdStr[n] = '\0';
+      break;
+    }
+  }
+
+  // Also: Look for "Content-Length:" (optional, case insensitive)
+  contentLength = 0; // default value
+  for (j = i; (int)j < (int)(reqStrSize-15); ++j) {
+    if (_strncasecmp("Content-Length:", &(reqStr[j]), 15) == 0) {
+      j += 15;
+      while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
+      unsigned num;
+      if (sscanf(&reqStr[j], "%u", &num) == 1) {
+       contentLength = num;
+      }
+    }
+  }
+  return True;
+}
+
+Boolean parseRangeParam(char const* paramStr,
+                       double& rangeStart, double& rangeEnd,
+                       char*& absStartTime, char*& absEndTime,
+                       Boolean& startTimeIsNow) {
+  delete[] absStartTime; delete[] absEndTime;
+  absStartTime = absEndTime = NULL; // by default, unless "paramStr" is a 
"clock=..." string
+  startTimeIsNow = False; // by default
+  double start, end;
+  int numCharsMatched1 = 0, numCharsMatched2 = 0, numCharsMatched3 = 0, 
numCharsMatched4 = 0;
+  int startHour = 0, startMin = 0, endHour = 0, endMin = 0;
+  double startSec = 0.0, endSec = 0.0;
+  Locale l("C", Numeric);
+  if (sscanf(paramStr, "npt = %d:%d:%lf - %d:%d:%lf", &startHour, &startMin, 
&startSec, &endHour, &endMin, &endSec) == 6) {
+    rangeStart = startHour*3600 + startMin*60 + startSec;
+    rangeEnd = endHour*3600 + endMin*60 + endSec;
+  } else if (sscanf(paramStr, "npt =%lf - %d:%d:%lf", &start, &endHour, 
&endMin, &endSec) == 4) {
+    rangeStart = start;
+    rangeEnd = endHour*3600 + endMin*60 + endSec;
+  } else if (sscanf(paramStr, "npt = %d:%d:%lf -", &startHour, &startMin, 
&startSec) == 3) {
+    rangeStart = startHour*3600 + startMin*60 + startSec;
+    rangeEnd = 0.0;
+  } else if (sscanf(paramStr, "npt = %lf - %lf", &start, &end) == 2) {
+    rangeStart = start;
+    rangeEnd = end;
+  } else if (sscanf(paramStr, "npt = %n%lf -", &numCharsMatched1, &start) == 
1) {
+    if (paramStr[numCharsMatched1] == '-') {
+      // special case for "npt = -<endtime>", which matches here:
+      rangeStart = 0.0; startTimeIsNow = True;
+      rangeEnd = -start;
+    } else {
+      rangeStart = start;
+      rangeEnd = 0.0;
+    }
+  } else if (sscanf(paramStr, "npt = now - %lf", &end) == 1) {
+      rangeStart = 0.0; startTimeIsNow = True;
+      rangeEnd = end;
+  } else if (sscanf(paramStr, "npt = now -%n", &numCharsMatched2) == 0 && 
numCharsMatched2 > 0) {
+    rangeStart = 0.0; startTimeIsNow = True;
+    rangeEnd = 0.0;
+  } else if (sscanf(paramStr, "clock = %n", &numCharsMatched3) == 0 && 
numCharsMatched3 > 0) {
+    rangeStart = rangeEnd = 0.0;
+
+    char const* utcTimes = &paramStr[numCharsMatched3];
+    size_t len = strlen(utcTimes) + 1;
+    char* as = new char[len];
+    char* ae = new char[len];
+    int sscanfResult = sscanf(utcTimes, "%[^-]-%[^\r\n]", as, ae);
+    if (sscanfResult == 2) {
+      absStartTime = as;
+      absEndTime = ae;
+    } else if (sscanfResult == 1) {
+      absStartTime = as;
+      delete[] ae;
+    } else {
+      delete[] as; delete[] ae;
+      return False;
+    }
+  } else if (sscanf(paramStr, "smtpe = %n", &numCharsMatched4) == 0 && 
numCharsMatched4 > 0) {
+    // We accept "smtpe=" parameters, but currently do not interpret them.
+  } else {
+    return False; // The header is malformed
+  }
+
+  return True;
+}
+
+Boolean parseRangeHeader(char const* buf,
+                        double& rangeStart, double& rangeEnd,
+                        char*& absStartTime, char*& absEndTime,
+                        Boolean& startTimeIsNow) {
+  // First, find "Range:"
+  while (1) {
+    if (*buf == '\0') return False; // not found
+    if (_strncasecmp(buf, "Range: ", 7) == 0) break;
+    ++buf;
+  }
+
+  char const* fields = buf + 7;
+  while (*fields == ' ') ++fields;
+  return parseRangeParam(fields, rangeStart, rangeEnd, absStartTime, 
absEndTime, startTimeIsNow);
+}
+
+Boolean parseScaleHeader(char const* buf, float& scale) {
+  // Initialize the result parameter to a default value:
+  scale = 1.0;
+
+  // First, find "Scale:"
+  while (1) {
+    if (*buf == '\0') return False; // not found
+    if (_strncasecmp(buf, "Scale:", 6) == 0) break;
+    ++buf;
+  }
+
+  char const* fields = buf + 6;
+  while (*fields == ' ') ++fields;
+  float sc;
+  if (sscanf(fields, "%f", &sc) == 1) {
+    scale = sc;
+  } else {
+    return False; // The header is malformed
+  }
+
+  return True;
+}
+
+// Used to implement "RTSPOptionIsSupported()":
+static Boolean isSeparator(char c) { return c == ' ' || c == ',' || c == ';' 
|| c == ':'; }
+
+Boolean RTSPOptionIsSupported(char const* commandName, char const* 
optionsResponseString) {
+  do {
+    if (commandName == NULL || optionsResponseString == NULL) break;
+
+    unsigned const commandNameLen = strlen(commandName);
+    if (commandNameLen == 0) break;
+
+    // "optionsResponseString" is assumed to be a list of command names, 
separated by " " and/or ",", ";", or ":"
+    // Scan through these, looking for "commandName".
+    while (1) {
+      // Skip over separators:
+      while (*optionsResponseString != '\0' && 
isSeparator(*optionsResponseString)) ++optionsResponseString;
+      if (*optionsResponseString == '\0') break;
+
+      // At this point, "optionsResponseString" begins with a command name 
(with perhaps a separator afterwads).
+      if (strncmp(commandName, optionsResponseString, commandNameLen) == 0) {
+       // We have at least a partial match here.
+       optionsResponseString += commandNameLen;
+       if (*optionsResponseString == '\0' || 
isSeparator(*optionsResponseString)) return True;
+      }
+
+      // No match.  Skip over the rest of the command name:
+      while (*optionsResponseString != '\0' && 
!isSeparator(*optionsResponseString)) ++optionsResponseString;
+    }
+  } while (0);
+
+  return False;
+}
+
+char const* dateHeader() {
+  static char buf[200];
+#if !defined(_WIN32_WCE)
+  time_t tt = time(NULL);
+  tm time_tm;
+#ifdef _WIN32
+  if (gmtime_s(&time_tm, &tt) != 0) {
+      time_tm = tm{};
+  }
+#else
+  if (gmtime_r(&tt, &time_tm) == NULL) {
+    time_tm = tm();
+  }
+#endif
+  static const char* day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 
};
+  static const char* month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+  snprintf(buf, sizeof buf, "Date: %s, %s %02d %04d %02d:%02d:%02d GMT\r\n",
+          day[time_tm.tm_wday], month[time_tm.tm_mon], time_tm.tm_mday,
+          1900 + time_tm.tm_year,
+          time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec);
+#else
+  // WinCE apparently doesn't have "time()", or "gmtime()",
+  // so generate the "Date:" header a different, WinCE-specific way.
+  // (Thanks to Pierre l'Hussiez for this code)
+  // RSF: But where is the "Date: " string?  This code doesn't look quite 
right...
+  SYSTEMTIME SystemTime;
+  GetSystemTime(&SystemTime);
+  WCHAR dateFormat[] = L"ddd, MMM dd yyyy";
+  WCHAR timeFormat[] = L"HH:mm:ss GMT\r\n";
+  WCHAR inBuf[200];
+  DWORD locale = LOCALE_NEUTRAL;
+
+  int ret = GetDateFormat(locale, 0, &SystemTime,
+                          (LPTSTR)dateFormat, (LPTSTR)inBuf, sizeof inBuf);
+  inBuf[ret - 1] = ' ';
+  ret = GetTimeFormat(locale, 0, &SystemTime,
+                      (LPTSTR)timeFormat,
+                      (LPTSTR)inBuf + ret, (sizeof inBuf) - ret);
+  wcstombs(buf, inBuf, wcslen(inBuf));
+#endif
+  return buf;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/SIPClient.cpp 
new/live/liveMedia/SIPClient.cpp
--- old/live/liveMedia/SIPClient.cpp    2023-11-30 09:22:23.000000000 +0100
+++ new/live/liveMedia/SIPClient.cpp    2024-06-26 07:46:23.000000000 +0200
@@ -107,7 +107,6 @@
 
   // Set the "User-Agent:" header to use in each request:
   char const* const libName = "LIVE555 Streaming Media v";
-  char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING;
   char const* libPrefix; char const* libSuffix;
   if (applicationName == NULL || applicationName[0] == '\0') {
     applicationName = libPrefix = libSuffix = "";
@@ -116,10 +115,10 @@
     libSuffix = ")";
   }
   unsigned userAgentNameSize
-    = fApplicationNameSize + strlen(libPrefix) + strlen(libName) + 
strlen(libVersionStr) + strlen(libSuffix) + 1;
+    = fApplicationNameSize + strlen(libPrefix) + strlen(libName) + 
strlen(liveMediaLibraryVersionStr) + strlen(libSuffix) + 1;
   char* userAgentName = new char[userAgentNameSize];
   sprintf(userAgentName, "%s%s%s%s%s",
-         applicationName, libPrefix, libName, libVersionStr, libSuffix);
+         applicationName, libPrefix, libName, liveMediaLibraryVersionStr, 
libSuffix);
   setUserAgentString(userAgentName);
   delete[] userAgentName;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/ServerMediaSession.cpp 
new/live/liveMedia/ServerMediaSession.cpp
--- old/live/liveMedia/ServerMediaSession.cpp   2023-11-30 09:22:23.000000000 
+0100
+++ new/live/liveMedia/ServerMediaSession.cpp   2024-06-26 07:46:23.000000000 
+0200
@@ -56,7 +56,6 @@
 }
 
 static char const* const libNameStr = "LIVE555 Streaming Media v";
-char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING;
 
 ServerMediaSession::ServerMediaSession(UsageEnvironment& env,
                                       char const* streamName,
@@ -71,8 +70,8 @@
 
   char* libNamePlusVersionStr = NULL; // by default
   if (info == NULL || description == NULL) {
-    libNamePlusVersionStr = new char[strlen(libNameStr) + 
strlen(libVersionStr) + 1];
-    sprintf(libNamePlusVersionStr, "%s%s", libNameStr, libVersionStr);
+    libNamePlusVersionStr = new char[strlen(libNameStr) + 
strlen(liveMediaLibraryVersionStr) + 1];
+    sprintf(libNamePlusVersionStr, "%s%s", libNameStr, 
liveMediaLibraryVersionStr);
   }
   fInfoSDPString = strDup(info == NULL ? libNamePlusVersionStr : info);
   fDescriptionSDPString = strDup(description == NULL ? libNamePlusVersionStr : 
description);
@@ -288,7 +287,7 @@
       + 20 + 6 + 20 + 3/*IP4 or IP6*/ + ipAddressStrSize
       + strlen(fDescriptionSDPString)
       + strlen(fInfoSDPString)
-      + strlen(libNameStr) + strlen(libVersionStr)
+      + strlen(libNameStr) + strlen(liveMediaLibraryVersionStr)
       + strlen(sourceFilterLine)
       + strlen(rangeLine)
       + strlen(fDescriptionSDPString)
@@ -306,7 +305,7 @@
             ipAddressStr.val(), // o= <address>
             fDescriptionSDPString, // s= <description>
             fInfoSDPString, // i= <info>
-            libNameStr, libVersionStr, // a=tool:
+            libNameStr, liveMediaLibraryVersionStr, // a=tool:
             sourceFilterLine, // a=source-filter: incl (if a SSM session)
             rangeLine, // a=range: line
             fDescriptionSDPString, // a=x-qt-text-nam: line
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/TLSState.cpp 
new/live/liveMedia/TLSState.cpp
--- old/live/liveMedia/TLSState.cpp     2023-11-30 09:22:23.000000000 +0100
+++ new/live/liveMedia/TLSState.cpp     2024-06-26 07:46:23.000000000 +0200
@@ -228,7 +228,7 @@
 
     if (SSL_CTX_set_ecdh_auto(fCtx, 1) != 1) break;
 
-    if (SSL_CTX_use_certificate_file(fCtx, fCertificateFileName, 
SSL_FILETYPE_PEM) != 1) break;
+    if (SSL_CTX_use_certificate_chain_file(fCtx, fCertificateFileName) != 1) 
break;
 
     if (SSL_CTX_use_PrivateKey_file(fCtx, fPrivateKeyFileName, 
SSL_FILETYPE_PEM) != 1) break;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/QuickTimeFileSink.hh 
new/live/liveMedia/include/QuickTimeFileSink.hh
--- old/live/liveMedia/include/QuickTimeFileSink.hh     2023-11-30 
09:22:23.000000000 +0100
+++ new/live/liveMedia/include/QuickTimeFileSink.hh     2024-06-26 
07:46:23.000000000 +0200
@@ -151,6 +151,8 @@
                           _atom(h263);
                           _atom(avc1);
                               _atom(avcC);
+                          _atom(hvc1);
+                              _atom(hvcC);
                           _atom(mp4v);
                           _atom(rtp);
                               _atom(tims);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/liveMedia_version.hh 
new/live/liveMedia/include/liveMedia_version.hh
--- old/live/liveMedia/include/liveMedia_version.hh     2023-11-30 
09:22:23.000000000 +0100
+++ new/live/liveMedia/include/liveMedia_version.hh     2024-06-26 
07:46:23.000000000 +0200
@@ -14,12 +14,15 @@
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **********/
 // Version information for the "liveMedia" library
-// Copyright (c) 1996-2023 Live Networks, Inc.  All rights reserved.
+// Copyright (c) 1996-2024 Live Networks, Inc.  All rights reserved.
 
 #ifndef _LIVEMEDIA_VERSION_HH
 #define _LIVEMEDIA_VERSION_HH
 
-#define LIVEMEDIA_LIBRARY_VERSION_STRING       "2023.11.30"
-#define LIVEMEDIA_LIBRARY_VERSION_INT          1701302400
+#define LIVEMEDIA_LIBRARY_VERSION_STRING       "2024.06.26"
+#define LIVEMEDIA_LIBRARY_VERSION_INT          1719360000
+
+extern char const* const liveMediaLibraryVersionStr;
+extern int const liveMediaLibraryVersionInt;
 
 #endif

Reply via email to